Leaked source code of windows server 2003
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.

391 lines
13 KiB

  1. /*++
  2. Copyright (c) 1991-1992 Microsoft Corporation
  3. Module Name:
  4. ErrConv.c
  5. Abstract:
  6. This file contains RxpConvertErrorLogArray.
  7. Author:
  8. John Rogers (JohnRo) 12-Nov-1991
  9. Environment:
  10. Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
  11. Requires ANSI C extensions: slash-slash comments, long external names.
  12. Notes:
  13. The logic in this routine is based on the logic in AudArray.c.
  14. Make sure that you check both files if you find a bug in either.
  15. Revision History:
  16. 12-Nov-1991 JohnRo
  17. Created.
  18. 05-Feb-1992 JohnRo
  19. Fix bug where zero bytes of data was mishandled.
  20. 14-Jun-1992 JohnRo
  21. RAID 10311: NetAuditRead and NetErrorLogRead pointer arithmetic wrong.
  22. Use PREFIX_ equates.
  23. 07-Jul-1992 JohnRo
  24. RAID 9933: ALIGN_WORST should be 8 for x86 builds.
  25. Made changes suggested by PC-LINT.
  26. 17-Aug-1992 JohnRo
  27. RAID 2920: Support UTC timezone in net code.
  28. 10-Sep-1992 JohnRo
  29. RAID 5174: event viewer _access violates after NetErrorRead.
  30. 23-Sep-1992 JohnRo
  31. Handle many more varieties of error log corruption.
  32. 01-Oct-1992 JohnRo
  33. RAID 3556: Added NetpSystemTimeToGmtTime() for DosPrint APIs.
  34. --*/
  35. // These must be included first:
  36. #include <windows.h> // IN, LPTSTR, etc.
  37. #include <lmcons.h> // LM20_SNLEN, NET_API_STATUS, etc.
  38. #include <lmerrlog.h> // Needed by rxerrlog.h
  39. // These may be included in any order:
  40. #include <align.h> // ALIGN_ and related equates.
  41. #include <lmapibuf.h> // NetApiBufferAllocate(), NetApiBufferFree().
  42. #include <lmerr.h> // NERR_, ERROR_, and NO_ERROR equates.
  43. #include <netdebug.h> // NetpKdPrint(()), FORMAT_ equates.
  44. #include <prefix.h> // PREFIX_ equates.
  45. #include <rxerrlog.h> // My prototype.
  46. #include <rxp.h> // RxpEstimateLogSize().
  47. #include <rxpdebug.h> // IF_DEBUG().
  48. #include <smbgtpt.h> // Smb{Get,Put} macros.
  49. #include <string.h> // memcpy(), strlen().
  50. #include <timelib.h> // NetpLocalTimeToGmtTime().
  51. #include <tstring.h> // NetpCopyStrToTStr(), STRLEN().
  52. #define DOWNLEVEL_FIXED_ENTRY_SIZE \
  53. ( 2 /* el_len */ \
  54. + 2 /* el_reserved */ \
  55. + 4 /* el_time */ \
  56. + 2 /* el_error */ \
  57. + LM20_SNLEN+1 /* el_name (in ASCII) */ \
  58. + 2 /* el_data_offset */ \
  59. + 2 ) /* el_nstrings */
  60. #define MIN_DOWNLEVEL_ENTRY_SIZE \
  61. ( DOWNLEVEL_FIXED_ENTRY_SIZE \
  62. + 2 ) /* el_len2 */
  63. NET_API_STATUS
  64. RxpConvertErrorLogArray(
  65. IN LPVOID InputArray,
  66. IN DWORD InputByteCount,
  67. OUT LPBYTE * OutputArrayPtr, // will be alloc'ed (free w/ NetApiBufferFree).
  68. OUT LPDWORD OutputByteCountPtr
  69. )
  70. {
  71. #ifdef REVISED_ERROR_LOG_STRUCT
  72. DWORD ErrorCode;
  73. const LPBYTE InputArrayEndPtr
  74. = (LPVOID) ( ((LPBYTE)InputArray) + InputByteCount );
  75. LPBYTE InputBytePtr;
  76. DWORD InputTextOffset; // start of text array (from el_data_offset)
  77. DWORD InputTotalEntrySize;
  78. LPBYTE InputFixedPtr;
  79. LPVOID OutputArray;
  80. DWORD OutputBytesUsed = 0;
  81. DWORD OutputEntrySizeSoFar;
  82. LPERROR_LOG OutputFixedPtr;
  83. LPTSTR OutputNamePtr;
  84. NET_API_STATUS Status;
  85. DWORD StringCount;
  86. //
  87. // Error check caller's parameters.
  88. // Set output parameters to make error handling easier below.
  89. // (Also check for memory faults while we're at it.)
  90. //
  91. if (OutputArrayPtr != NULL) {
  92. *OutputArrayPtr = NULL;
  93. }
  94. if (OutputByteCountPtr != NULL) {
  95. *OutputByteCountPtr = 0;
  96. }
  97. if ( (OutputArrayPtr == NULL) || (OutputByteCountPtr == NULL) ) {
  98. return (ERROR_INVALID_PARAMETER); // (output variables already set.)
  99. }
  100. if ( (InputArray == NULL) || (InputByteCount == 0) ) {
  101. return (ERROR_INVALID_PARAMETER); // (output variables already set.)
  102. }
  103. //
  104. // Estimate size needed for output array (due to expansion and alignment).
  105. //
  106. Status = RxpEstimateLogSize(
  107. DOWNLEVEL_FIXED_ENTRY_SIZE,
  108. InputByteCount, // input (downlevel) array size in bytes.
  109. TRUE, // yes, these are error log entries.
  110. OutputByteCountPtr);// set total number of bytes needed.
  111. if (Status != NO_ERROR) {
  112. return (Status); // (output variables already set.)
  113. }
  114. NetpAssert( *OutputByteCountPtr > 0 );
  115. //
  116. // Allocate oversize area for output; we'll realloc it to shrink it.
  117. //
  118. Status = NetApiBufferAllocate(
  119. *OutputByteCountPtr,
  120. (LPVOID *) & OutputArray );
  121. if (Status != NO_ERROR) {
  122. return (Status); // (output variables already set.)
  123. }
  124. NetpAssert( POINTER_IS_ALIGNED( OutputArray, ALIGN_WORST ) );
  125. //
  126. // Loop for each entry in the input area.
  127. //
  128. OutputFixedPtr = OutputArray;
  129. for (InputBytePtr = InputArray; InputBytePtr < InputArrayEndPtr; ) {
  130. InputFixedPtr = InputBytePtr;
  131. // Code at end of loop makes sure that next entry will be aligned.
  132. // Double check that here.
  133. NetpAssert( POINTER_IS_ALIGNED(OutputFixedPtr, ALIGN_WORST) );
  134. IF_DEBUG(ERRLOG) {
  135. NetpKdPrint(( PREFIX_NETAPI
  136. "RxpConvertErrorLogArray: doing input entry at "
  137. FORMAT_LPVOID ", out entry at " FORMAT_LPVOID ".\n",
  138. (LPVOID) InputFixedPtr, (LPVOID) OutputFixedPtr ));
  139. }
  140. //
  141. // Process each field in input fixed entry. We'll do the name
  142. // here as well. (The name is in the input fixed entry, although it
  143. // was moved to the variable part for the new structure layout.)
  144. //
  145. OutputEntrySizeSoFar = sizeof(ERROR_LOG);
  146. InputTotalEntrySize = (DWORD) SmbGetUshort( (LPWORD) InputBytePtr );
  147. if (InputTotalEntrySize < MIN_DOWNLEVEL_ENTRY_SIZE) {
  148. goto FileCorrupt;
  149. }
  150. {
  151. LPBYTE EndPos = InputBytePtr + InputTotalEntrySize;
  152. if (EndPos > InputArrayEndPtr) {
  153. goto FileCorrupt;
  154. }
  155. EndPos -= sizeof(WORD); // the last el_len2
  156. if (SmbGetUshort( (LPWORD) EndPos ) != InputTotalEntrySize) {
  157. goto FileCorrupt;
  158. }
  159. }
  160. InputBytePtr += sizeof(WORD); // skip el_len.
  161. {
  162. WORD Reserved = SmbGetUshort( (LPWORD) InputBytePtr );
  163. WORD InvertedSize = ~ (WORD) InputTotalEntrySize;
  164. if (Reserved != InvertedSize) {
  165. goto FileCorrupt;
  166. }
  167. OutputFixedPtr->el_reserved = Reserved;
  168. }
  169. InputBytePtr += sizeof(WORD); // skip el_reserved.
  170. {
  171. DWORD LocalTime = (DWORD) SmbGetUlong( (LPDWORD) InputBytePtr );
  172. DWORD GmtTime;
  173. NetpLocalTimeToGmtTime( LocalTime, & GmtTime );
  174. OutputFixedPtr->el_time = GmtTime;
  175. InputBytePtr += sizeof(DWORD);
  176. }
  177. ErrorCode = (DWORD) SmbGetUshort( (LPWORD) InputBytePtr );
  178. NetpAssert( ErrorCode != 0 );
  179. OutputFixedPtr->el_error = ErrorCode;
  180. InputBytePtr += sizeof(WORD);
  181. OutputNamePtr = (LPTSTR)
  182. ( ((LPBYTE)OutputFixedPtr) + sizeof(ERROR_LOG) );
  183. OutputNamePtr = ROUND_UP_POINTER( OutputNamePtr, ALIGN_TCHAR );
  184. OutputEntrySizeSoFar
  185. = ROUND_UP_COUNT( OutputEntrySizeSoFar, ALIGN_TCHAR );
  186. NetpCopyStrToTStr(
  187. OutputNamePtr, // dest
  188. (LPVOID) InputBytePtr); // src
  189. OutputEntrySizeSoFar += STRSIZE(OutputNamePtr); // string and null chr
  190. OutputFixedPtr->el_name = OutputNamePtr;
  191. InputBytePtr += LM20_SNLEN+1;
  192. InputTextOffset = (DWORD) SmbGetUshort( (LPWORD) InputBytePtr );
  193. NetpAssert( InputTextOffset >= DOWNLEVEL_FIXED_ENTRY_SIZE );
  194. InputBytePtr += sizeof(WORD);
  195. StringCount = (DWORD) SmbGetUshort( (LPWORD) InputBytePtr );
  196. OutputFixedPtr->el_nstrings = StringCount;
  197. InputBytePtr += sizeof(WORD);
  198. //
  199. // Process text portion (if any).
  200. //
  201. {
  202. LPTSTR NextOutputString;
  203. // Start text strings after (aligned) name string.
  204. NextOutputString = (LPVOID)
  205. ( ((LPBYTE) OutputFixedPtr) + OutputEntrySizeSoFar );
  206. // Make sure we've processed entire input fixed entry.
  207. NetpAssert(
  208. InputBytePtr == (InputFixedPtr + DOWNLEVEL_FIXED_ENTRY_SIZE));
  209. // Use offset of text area (was misnamed el_data_offset).
  210. // InputBytePtr = InputFixedPtr + InputTextOffset;
  211. NetpAssert(
  212. InputBytePtr >= (InputFixedPtr + DOWNLEVEL_FIXED_ENTRY_SIZE));
  213. if (StringCount > 0) {
  214. OutputFixedPtr->el_text = NextOutputString;
  215. while (StringCount > 0) {
  216. DWORD InputStringSize = strlen( (LPVOID) InputBytePtr) + 1;
  217. DWORD OutputStringSize = InputStringSize * sizeof(TCHAR);
  218. NetpCopyStrToTStr(
  219. NextOutputString, // dest
  220. (LPSTR) InputBytePtr); // src
  221. InputBytePtr += InputStringSize;
  222. NextOutputString += InputStringSize;
  223. OutputEntrySizeSoFar += OutputStringSize;
  224. --StringCount;
  225. }
  226. } else {
  227. OutputFixedPtr->el_text = NULL;
  228. }
  229. }
  230. NetpAssert( COUNT_IS_ALIGNED(OutputEntrySizeSoFar, ALIGN_TCHAR) );
  231. //
  232. // Process "data" (byte array) portion (if any).
  233. //
  234. {
  235. DWORD InputDataSize; // byte count for el_data only.
  236. NetpAssert( InputBytePtr > InputFixedPtr );
  237. // Use offset of data area.
  238. InputBytePtr = InputFixedPtr + InputTextOffset;
  239. InputDataSize = (DWORD)
  240. ( (InputTotalEntrySize - sizeof(WORD))
  241. - (InputBytePtr - InputFixedPtr) );
  242. if ( InputDataSize > 0 ) {
  243. LPBYTE OutputDataPtr
  244. = ((LPBYTE) OutputFixedPtr + OutputEntrySizeSoFar);
  245. NetpAssert( ALIGN_BYTE == 1 ); // align here if not.
  246. (void) memcpy(
  247. OutputDataPtr, // dest
  248. InputBytePtr, // src
  249. InputDataSize); // byte count
  250. InputBytePtr += InputDataSize;
  251. OutputEntrySizeSoFar += InputDataSize;
  252. OutputFixedPtr->el_data = OutputDataPtr;
  253. // Store correct byte count (before padding).
  254. OutputFixedPtr->el_data_size = InputDataSize;
  255. } else {
  256. OutputFixedPtr->el_data = NULL;
  257. OutputFixedPtr->el_data_size = 0;
  258. }
  259. }
  260. //
  261. // The final thing (even after alignment padding) is el_len2.
  262. //
  263. OutputEntrySizeSoFar += sizeof(DWORD);
  264. // Round size up so next entry (if any) is worst-case aligned.
  265. OutputEntrySizeSoFar =
  266. ROUND_UP_COUNT( OutputEntrySizeSoFar, ALIGN_WORST );
  267. #define OutputEntrySize OutputEntrySizeSoFar
  268. //
  269. // That's all. Now go back and set both lengths for this entry.
  270. //
  271. OutputFixedPtr->el_len = OutputEntrySize;
  272. {
  273. LPDWORD EndSizePtr = (LPVOID)
  274. ( ((LPBYTE)OutputFixedPtr)
  275. + OutputEntrySize - sizeof(DWORD) );
  276. *EndSizePtr = OutputEntrySize; // set el_len2.
  277. }
  278. //
  279. // Update for next loop iteration.
  280. //
  281. InputBytePtr = (LPVOID)
  282. ( ((LPBYTE) InputFixedPtr) + InputTotalEntrySize);
  283. OutputFixedPtr = (LPVOID)
  284. ( ((LPBYTE) OutputFixedPtr) + OutputEntrySize );
  285. OutputBytesUsed += OutputEntrySize;
  286. }
  287. NetpAssert(OutputBytesUsed > 0);
  288. *OutputArrayPtr = OutputArray;
  289. *OutputByteCountPtr = OutputBytesUsed;
  290. return (NO_ERROR);
  291. FileCorrupt:
  292. NetpKdPrint(( PREFIX_NETAPI
  293. "RxpConvertErrorLogArray: corrupt error log!\n" ));
  294. if (OutputArray != NULL) {
  295. (VOID) NetApiBufferFree( OutputArray );
  296. }
  297. if (OutputArrayPtr != NULL) {
  298. *OutputArrayPtr = NULL;
  299. }
  300. if (OutputByteCountPtr != NULL) {
  301. *OutputByteCountPtr = 0;
  302. }
  303. return (NERR_LogFileCorrupt);
  304. #else // not REVISED_ERROR_LOG_STRUCT
  305. return (ERROR_NOT_SUPPORTED);
  306. #endif
  307. }