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.

626 lines
14 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. dbgutil.hxx
  6. Abstract:
  7. LSA Utility functions header
  8. Author:
  9. Larry Zhu (Lzhu) May 1, 2001
  10. Revision History:
  11. --*/
  12. #ifndef _LSAUTIL_HXX_
  13. #define _LSAUTIL_HXX_
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <align.h>
  17. namespace LSA_NS {
  18. enum ELsaExceptionCode {
  19. kInvalid,
  20. kIncorrectSymbols,
  21. kExitOnControlC,
  22. };
  23. LPCTSTR
  24. StripPathFromFileName(
  25. IN LPCTSTR pszFile
  26. );
  27. ULONG
  28. GetStructFieldVerbose(
  29. IN ULONG64 addrStructBase,
  30. IN PCSTR pszStructTypeName,
  31. IN PCSTR pszStructFieldName,
  32. IN ULONG BufferSize,
  33. OUT PVOID Buffer);
  34. ULONG
  35. GetStructPtrFieldVerbose(
  36. IN ULONG64 addrStructBase,
  37. IN PCSTR pszStructTypeName,
  38. IN PCSTR pszStructFieldName,
  39. OUT PULONG64 Buffer);
  40. HRESULT
  41. GetCurrentProcessor(
  42. IN PDEBUG_CLIENT Client,
  43. OPTIONAL OUT PULONG pProcessor,
  44. OPTIONAL OUT PHANDLE phCurrentThread);
  45. PCSTR
  46. ReadStructStrField(
  47. IN ULONG64 addrStructBase,
  48. IN PCSTR pszStructTypeName,
  49. IN PCSTR pszStructStringFieldName);
  50. PCWSTR
  51. ReadStructWStrField(
  52. IN ULONG64 addrStructBase,
  53. IN PCSTR pszStructTypeName,
  54. IN PCSTR pszStructWStringFieldName);
  55. BOOL
  56. WINAPI
  57. LsaLookupAccountNameA(
  58. IN LPCSTR lpSystemName,
  59. IN LPCSTR lpAccountName,
  60. OUT PSID Sid,
  61. IN OUT LPDWORD cbSid,
  62. OUT LPSTR ReferencedDomainName,
  63. IN OUT LPDWORD cbReferencedDomainName,
  64. OUT PSID_NAME_USE peUse
  65. );
  66. BOOL
  67. WINAPI
  68. LsaLookupAccountSidA(
  69. IN LPCSTR lpSystemName,
  70. IN PSID Sid,
  71. OUT LPSTR Name,
  72. IN OUT LPDWORD cbName,
  73. OUT LPSTR ReferencedDomainName,
  74. IN OUT LPDWORD cbReferencedDomainName,
  75. OUT PSID_NAME_USE peUse
  76. );
  77. void LocalPrintGuid(IN const GUID *pGuid);
  78. BOOL IsAddressInNonePAEKernelAddressSpace(IN ULONG64 addr);
  79. HRESULT HResultFromWin32(IN DWORD dwError);
  80. HRESULT GetLastErrorAsHResult(void);
  81. BOOLEAN IsEmpty(IN PCSTR pszArgs);
  82. void debugPrintHandle(IN HANDLE handle);
  83. NTSTATUS NtStatusFromWin32(IN DWORD dwError);
  84. NTSTATUS GetLastErrorAsNtStatus(void);
  85. HRESULT ProcessKnownOptions(IN PCSTR pszArgs OPTIONAL);
  86. HRESULT ProcessHelpRequest(IN PCSTR pszArgs OPTIONAL);
  87. LARGE_INTEGER
  88. ULONG642LargeInteger(
  89. IN ULONG64 value
  90. );
  91. VOID
  92. ShowSystemTimeAsLocalTime(
  93. IN PCSTR pszBanner,
  94. IN ULONG64 ul64Time
  95. );
  96. void handleLsaException(
  97. IN ELsaExceptionCode eExceptionCode,
  98. IN PCSTR pszMsg, OPTIONAL
  99. IN PCSTR pszSymHint OPTIONAL
  100. );
  101. HRESULT GetFileNamePart(IN PCSTR pszFullPath, OUT PCSTR *ppszFileName);
  102. void debugPrintHex(IN const void* buffer, IN ULONG cbBuffer);
  103. #define LSA_NONE 0x00
  104. #define LSA_WARN 0x01
  105. #define LSA_ERROR 0x02
  106. #define LSA_LOG 0x04
  107. #define LSA_LOG_MORE 0x08
  108. #define LSA_LOG_ALL 0x10
  109. inline void debugPrintLevel(IN ULONG ulLevel)
  110. {
  111. PCSTR pszText = NULL;
  112. switch (ulLevel) {
  113. case LSA_WARN:
  114. pszText = "[warn] ";
  115. break;
  116. case LSA_ERROR:
  117. pszText = "[error] ";
  118. break;
  119. case LSA_LOG:
  120. pszText = "[log] ";
  121. break;
  122. case LSA_LOG_MORE:
  123. pszText = "[more] ";
  124. break;
  125. case LSA_LOG_ALL:
  126. pszText = "[all] ";
  127. break;
  128. default:
  129. pszText = kstrInvalid;
  130. break;
  131. }
  132. OutputDebugStringA(pszText);
  133. }
  134. inline void debugPrintf(IN PCSTR pszFmt, ...)
  135. {
  136. CHAR szBuffer[4096] = {0};
  137. OutputDebugStringA(g_Globals.pszDbgPrompt ? g_Globals.pszDbgPrompt : kstrEmptyA);
  138. va_list pArgs;
  139. va_start(pArgs, pszFmt);
  140. _vsnprintf(szBuffer, sizeof(szBuffer) - 1, pszFmt, pArgs);
  141. OutputDebugStringA(szBuffer);
  142. va_end(pArgs);
  143. }
  144. inline PCSTR IoctlErrorStatusToStr(IN PCSTR pszPad, IN ULONG err)
  145. {
  146. static CHAR szBuf[1024] = {0};
  147. #define BRANCH_AND_PRINT(x) \
  148. \
  149. do { \
  150. if (x == err) { \
  151. _snprintf(szBuf, sizeof(szBuf) - 1, "%s%s", pszPad, #x); \
  152. return szBuf; \
  153. } \
  154. } while (0)
  155. BRANCH_AND_PRINT(MEMORY_READ_ERROR);
  156. BRANCH_AND_PRINT(SYMBOL_TYPE_INDEX_NOT_FOUND);
  157. BRANCH_AND_PRINT(SYMBOL_TYPE_INFO_NOT_FOUND);
  158. BRANCH_AND_PRINT(FIELDS_DID_NOT_MATCH);
  159. BRANCH_AND_PRINT(NULL_SYM_DUMP_PARAM);
  160. BRANCH_AND_PRINT(NULL_FIELD_NAME);
  161. BRANCH_AND_PRINT(INCORRECT_VERSION_INFO);
  162. BRANCH_AND_PRINT(EXIT_ON_CONTROLC);
  163. BRANCH_AND_PRINT(CANNOT_ALLOCATE_MEMORY);
  164. BRANCH_AND_PRINT(INSUFFICIENT_SPACE_TO_COPY);
  165. #undef BRANCH_AND_PRINT
  166. _snprintf(szBuf, sizeof(szBuf) - 1, "%s%#x", pszPad, err);
  167. return szBuf;
  168. }
  169. BOOL IsPtr64WithVoidStar(void);
  170. inline ULONG64 toPtr(IN ULONG64 addr)
  171. {
  172. static BOOL bIsPtr64 = IsPtr64WithVoidStar();
  173. if (!bIsPtr64) {
  174. addr = static_cast<ULONG>(addr);
  175. }
  176. return addr;
  177. }
  178. inline ULONG GetPtrSize(void)
  179. {
  180. static ULONG cbPtrSize = 0;
  181. if (!cbPtrSize) {
  182. cbPtrSize = IsPtr64WithVoidStar() ? sizeof(ULONG64) : sizeof(ULONG);
  183. }
  184. return cbPtrSize;
  185. }
  186. inline ULONG ReadPtrSize(void)
  187. {
  188. static ULONG cbPtrSize = GetPtrSize();
  189. if (!cbPtrSize) {
  190. throw "ReadPtrSize failed";
  191. }
  192. return cbPtrSize;
  193. }
  194. inline ULONG GetPtrWithVoidStar(IN ULONG64 Addr, IN ULONG64* pPointer)
  195. {
  196. return GetFieldData(Addr, kstrVoidStar, NULL, sizeof(ULONG64), (PVOID) pPointer);
  197. }
  198. inline PCSTR EasyStr(IN PCSTR pszName)
  199. {
  200. return pszName ? pszName : kstrNullPtrA;
  201. }
  202. inline void HandleIoctlErrors(IN PCSTR pszBanner, IN ULONG ErrorCode)
  203. {
  204. if (SYMBOL_TYPE_INFO_NOT_FOUND == ErrorCode) {
  205. throw kIncorrectSymbols;
  206. } else if (ErrorCode) {
  207. DBG_LOG(LSA_ERROR, ("%s: Ioctl failed with error code %s\n", EasyStr(pszBanner), EasyStr(IoctlErrorStatusToStr(kstrEmptyA, ErrorCode))));
  208. throw "Ioctl failed";
  209. }
  210. }
  211. inline ULONG64 ReadPtrWithVoidStar(IN ULONG64 Addr)
  212. {
  213. ULONG64 Pointer = 0;
  214. HandleIoctlErrors("ReadPtrWithVoidStar", GetFieldData(Addr, kstrVoidStar, NULL, sizeof(ULONG64), &Pointer));
  215. return Pointer;
  216. }
  217. inline ULONG64 ReadStructPtrField(IN ULONG64 addrStructBase, IN PCSTR pszStructTypeName, IN PCSTR pszStructFieldName)
  218. {
  219. ULONG64 addr = 0;
  220. DBG_LOG(LSA_LOG, ("ReadStructPtrField %s %#I64x %s\n", EasyStr(pszStructTypeName), addrStructBase, EasyStr(pszStructFieldName)));
  221. HandleIoctlErrors("ReadStructPtrField", GetStructPtrFieldVerbose(addrStructBase, pszStructTypeName, pszStructFieldName, &addr));
  222. return toPtr(addr);
  223. }
  224. inline ULONG64 ForwardAdjustPtrAddr(IN ULONG64 addr)
  225. {
  226. static ULONG uPtrSize = ReadPtrSize();
  227. ULONG64 alignedPtrAddr = addr;
  228. //
  229. // Only 64bit machines have alignment requirement
  230. //
  231. if (uPtrSize == sizeof(ULONG64)) {
  232. alignedPtrAddr = ROUND_UP_COUNT(addr, sizeof(ULONG64)); // ((addr + uPtrSize - 1) / uPtrSize) * uPtrSize;
  233. if (alignedPtrAddr != addr) {
  234. DBG_LOG(LSA_LOG, ("ForwardAdjustPtrAddr adjusted addr from %#I64x to %#I64x\n", addr, alignedPtrAddr));
  235. }
  236. }
  237. return alignedPtrAddr;
  238. }
  239. inline ULONG64 ReadPtrVar(IN ULONG64 addr)
  240. {
  241. static uPtrSize = ReadPtrSize();
  242. ULONG64 value = 0;
  243. ULONG errorCode = 0;
  244. //
  245. // Assume 64 bit machine has alignment requirement for pointers
  246. //
  247. if (uPtrSize == sizeof(ULONG64)) {
  248. ULONG64 alignedAddr = addr;
  249. alignedAddr = ForwardAdjustPtrAddr(addr);
  250. if (alignedAddr != addr) {
  251. DBG_LOG(LSA_WARN, ("Adjust pointer address %#I64x to 8 byte boundary %#I64x\n", addr, alignedAddr));
  252. }
  253. addr = alignedAddr;
  254. }
  255. HandleIoctlErrors("ReadPtrVar", GetPtrWithVoidStar(addr, &value));
  256. return toPtr(value);
  257. }
  258. inline UCHAR ReadUCHARVar(IN ULONG64 addr)
  259. {
  260. UCHAR value = 0;
  261. if (!ReadMemory(addr, &value, sizeof(value), NULL)) {
  262. DBG_LOG(LSA_ERROR, ("Can not ReadUCHARVar at %#I64x\n", addr));
  263. throw "ReadUCHARVar failed";
  264. }
  265. return value;
  266. }
  267. inline USHORT ReadUSHORTVar(IN ULONG64 addr)
  268. {
  269. USHORT value = 0;
  270. if (!ReadMemory(addr, &value, sizeof(value), NULL)) {
  271. DBG_LOG(LSA_ERROR, ("Can not ReadUSHORTVar at %#I64x\n", addr));
  272. throw "ReadUSHORTVar failed";
  273. }
  274. return value;
  275. }
  276. inline ULONG ReadULONGVar(IN ULONG64 addr)
  277. {
  278. ULONG value = 0;
  279. if (!ReadMemory(addr, &value, sizeof(value), NULL)) {
  280. DBG_LOG(LSA_ERROR, ("Can not ReadULONGVar at %#I64x\n", addr));
  281. throw "ReadULONGVar failed";
  282. }
  283. return value;
  284. }
  285. inline ULONG64 ReadULONG64Var(IN ULONG64 addr)
  286. {
  287. ULONG64 value = 0;
  288. if (!ReadMemory(addr, &value, sizeof(value), NULL)) {
  289. DBG_LOG(LSA_ERROR, ("Can not ReadULONG64Var at %#I64x\n", addr));
  290. throw "ReadULONG64Var failed";
  291. }
  292. return value;
  293. }
  294. inline ULONG ReadTypeSize(IN PCSTR pszTypeName)
  295. {
  296. ULONG typeSize = 0;
  297. typeSize = GetTypeSize(pszTypeName);
  298. DBG_LOG(LSA_LOG, ("Read type size of \"%s\"\n", EasyStr(pszTypeName)));
  299. if (!typeSize) {
  300. DBG_LOG(LSA_ERROR, ("Can not GetTypeSize on %s\n", EasyStr(pszTypeName)));
  301. throw "ReadTypeSize failed\n";
  302. }
  303. return typeSize;
  304. }
  305. inline ULONG ReadFieldOffset(IN PCSTR pszTypeName, IN PCSTR pszFieldName)
  306. {
  307. ULONG fieldOffset = 0;
  308. DBG_LOG(LSA_LOG, ("Read field offset of \"%s\" from \"%s\"\n", EasyStr(pszFieldName), EasyStr(pszTypeName)));
  309. HandleIoctlErrors("ReadFieldOffset", GetFieldOffset(pszTypeName, pszFieldName, &fieldOffset));
  310. return fieldOffset;
  311. }
  312. inline void ReadStructField(IN ULONG64 addrStructBase, IN PCSTR pszStructTypeName, IN PCSTR pszStructFieldName, IN ULONG fieldSize, OUT void* pFieldValue)
  313. {
  314. DBG_LOG(LSA_LOG, ("ReadStructField %s %#I64x %s\n", EasyStr(pszStructTypeName), addrStructBase, EasyStr(pszStructFieldName)));
  315. HandleIoctlErrors("ReadStructField", GetStructFieldVerbose(addrStructBase, pszStructTypeName, pszStructFieldName, fieldSize, pFieldValue));
  316. }
  317. inline void LsaReadMemory(IN ULONG64 addr, IN ULONG cbBuffer, OUT void* buffer)
  318. {
  319. if (!ReadMemory(addr, buffer, cbBuffer, NULL)) {
  320. DBG_LOG(LSA_ERROR, ("Unable to read %#x bytes from memory location %#I64x\n", cbBuffer, toPtr(addr)));
  321. throw "LsaReadMemory failed";
  322. }
  323. }
  324. //
  325. // Used to read in value of a short (<= 8 bytes) fields
  326. //
  327. // This is essentially the same as GetShortField with one difference that
  328. // it throws exceptions on failures
  329. //
  330. inline ULONG64 ReadShortField(IN ULONG64 TypeAddress, IN PCSTR pszName, IN USHORT StoreAddress)
  331. {
  332. static ULONG64 SavedAddress = 0;
  333. static PCSTR pszSavedName = NULL;
  334. static ULONG ReadPhysical = 0;
  335. ULONG Err = 0;
  336. FIELD_INFO flds = {reinterpret_cast<UCHAR*>(const_cast<PSTR>(pszName)), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL};
  337. SYM_DUMP_PARAM Sym = {
  338. sizeof (SYM_DUMP_PARAM), reinterpret_cast<UCHAR*>(const_cast<PSTR>(pszSavedName)), DBG_DUMP_NO_PRINT | ((StoreAddress & 2) ? DBG_DUMP_READ_PHYSICAL : 0),
  339. SavedAddress, NULL, NULL, NULL, 1, &flds
  340. };
  341. if (StoreAddress) {
  342. Sym.sName = reinterpret_cast<UCHAR*>(const_cast<PSTR>(pszName));
  343. Sym.nFields = 0;
  344. pszSavedName = pszName;
  345. Sym.addr = SavedAddress = TypeAddress;
  346. ReadPhysical = (StoreAddress & 2);
  347. if (!SavedAddress) {
  348. throw "Invalid arguments to ReadShortField";
  349. }
  350. Err = Ioctl(IG_DUMP_SYMBOL_INFO, &Sym, Sym.size);
  351. DBG_LOG(LSA_LOG, ("Save address %s %#I64x\n", EasyStr(pszName), TypeAddress));
  352. HandleIoctlErrors("ReadShortField (save address) failed", Err);
  353. return 0; // zero on success
  354. } else {
  355. Sym.Options |= ReadPhysical ? DBG_DUMP_READ_PHYSICAL : 0;
  356. }
  357. Err = Ioctl(IG_DUMP_SYMBOL_INFO, &Sym, Sym.size);
  358. DBG_LOG(LSA_LOG, ("Read %s %#I64x %s\n", EasyStr(pszSavedName), SavedAddress, EasyStr(pszName)));
  359. HandleIoctlErrors("ReadShortField (read value) failed", Err);
  360. return flds.address;
  361. }
  362. inline ULONG ReadTypeSizeInArray(IN PCSTR pszType)
  363. {
  364. ULONG cbOneItem = 0;
  365. ULONG cbTwoItems = 0;
  366. CHAR szTypeTmp[256] = {0};
  367. DBG_LOG(LSA_LOG, ("ReadTypeSizeInArray %s\n", pszType));
  368. cbOneItem = GetTypeSize(pszType);
  369. if (_snprintf(szTypeTmp, sizeof(szTypeTmp) - 1, "%s[2]", pszType) < 0) {
  370. throw "ReadTypeSizeInArray failed with insufficient buffer";
  371. }
  372. cbTwoItems = GetTypeSize(szTypeTmp);
  373. cbOneItem = cbTwoItems - cbOneItem;
  374. if (!cbOneItem) {
  375. dprintf("Unable to read type size in array for %s\n", pszType);
  376. throw "ReadTypeSizeInArray failed";
  377. }
  378. return cbOneItem;
  379. }
  380. inline ULONG64 ReadPtrField(IN PCSTR Field)
  381. {
  382. return toPtr(ReadShortField(0, Field, 0));
  383. }
  384. inline void ExitIfControlC(void)
  385. {
  386. if (CheckControlC()) {
  387. throw kExitOnControlC;
  388. }
  389. }
  390. //
  391. // This func is not thread safe
  392. //
  393. inline PCSTR PtrToStr(IN ULONG64 addr)
  394. {
  395. static CHAR szBuffer[64] = {0};
  396. if (!addr) {
  397. return kstrNullPtrA;
  398. }
  399. _snprintf(szBuffer, sizeof(szBuffer) - 1, "%#I64x", addr);
  400. return szBuffer;
  401. }
  402. //
  403. // This func is not thread safe because it calls PtrToStr which is not
  404. // thread safe
  405. //
  406. inline PCSTR GetSymbolStr(IN ULONG64 addr, IN PCSTR pszBuffer)
  407. {
  408. ExitIfControlC();
  409. //
  410. // null
  411. //
  412. if (!addr) {
  413. return kstrNullPtrA;
  414. }
  415. //
  416. // No symbols resolved, return address
  417. //
  418. if (!pszBuffer || !*pszBuffer) {
  419. return PtrToStr(addr);
  420. }
  421. //
  422. // Return symbols
  423. //
  424. return pszBuffer;
  425. }
  426. inline void PrintPtrWithSymbolsLn(IN PCSTR pszBanner, IN ULONG64 addr)
  427. {
  428. CHAR szBuffer[MAX_PATH] = {0};
  429. ULONG64 Disp = 0;
  430. GetSymbol(addr, szBuffer, &Disp);
  431. dprintf(kstr2StrLn, pszBanner, GetSymbolStr(addr, szBuffer));
  432. }
  433. inline void PrintSpaces(IN LONG cSpaces)
  434. {
  435. for (LONG i = 0; i < cSpaces; i++) {
  436. dprintf(kstrSpace);
  437. }
  438. }
  439. } // LSA_NS
  440. #endif