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.

510 lines
11 KiB

  1. #include "precomp.h"
  2. typedef struct _VLOG_GLOBAL_DATA {
  3. BOOL bLoggingDisabled;
  4. WCHAR szSessionLog[MAX_PATH];
  5. WCHAR szProcessLog[MAX_PATH];
  6. } VLOG_GLOBAL_DATA, *PVLOG_GLOBAL_DATA;
  7. PVLOG_GLOBAL_DATA g_pData = NULL;
  8. HANDLE g_hMap = NULL; // mapping handle for global data
  9. BOOL g_bVerifierLogInited = FALSE; // have we been through the init sequence?
  10. BOOL g_bLoggingDisabled = TRUE; // have we been through the init sequence?
  11. WCHAR g_szSessionLog[MAX_PATH];
  12. WCHAR g_szProcessLog[MAX_PATH];
  13. #define DEBUGGER_LOG L"DEBUGGER"
  14. #define DEBUGGER_ENTRY_CRASH L"Crash"
  15. #define DEBUGGER_ENTRY_CRASH_DESCRIPTION L"An AV occured. The application exited."
  16. void
  17. WriteToProcessLog(
  18. LPCSTR szLine
  19. );
  20. void
  21. WriteToSessionLog(
  22. LPCSTR szLine
  23. );
  24. void
  25. GetExeName(
  26. LPWSTR szProcessPath,
  27. LPWSTR szProcessName
  28. )
  29. {
  30. LPWSTR pszLast = NULL;
  31. LPWSTR psz;
  32. LPWSTR pszFound = NULL;
  33. psz = szProcessPath;
  34. while (psz) {
  35. pszFound = wcschr(psz, L'\\');
  36. if (pszFound != NULL) {
  37. pszLast = pszFound;
  38. psz = pszFound + 1;
  39. } else {
  40. psz = pszFound;
  41. }
  42. }
  43. if (pszLast != NULL) {
  44. psz = pszLast + 1;
  45. } else {
  46. psz = szProcessPath;
  47. }
  48. pszFound = wcschr(psz, L'.');
  49. if (pszFound != NULL) {
  50. wcsncpy(szProcessName, psz, pszFound - psz);
  51. } else {
  52. wcscpy(szProcessName, psz);
  53. }
  54. }
  55. /*++
  56. Function Description:
  57. Initializes the support for file logging.
  58. Return Value:
  59. TRUE if successful, FALSE if failed
  60. History:
  61. 04/26/2001 dmunsil Created
  62. --*/
  63. BOOL
  64. InitVerifierLogSupport(
  65. LPWSTR szProcessPath,
  66. DWORD dwID
  67. )
  68. {
  69. WCHAR szShared[128];
  70. WCHAR szVLogPath[MAX_PATH];
  71. WCHAR szProcessName[MAX_PATH];
  72. WCHAR szTime[128];
  73. char szTemp[400];
  74. HANDLE hFile;
  75. SYSTEMTIME LocalTime;
  76. int nTemp;
  77. BOOL bAlreadyInited;
  78. DWORD dwErr;
  79. //
  80. // if we've already been inited, get out
  81. //
  82. if (g_bVerifierLogInited) {
  83. return FALSE;
  84. }
  85. g_bVerifierLogInited = TRUE;
  86. swprintf(szShared, L"VeriferLog_%08X", dwID);
  87. g_hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szShared);
  88. if (g_hMap) {
  89. bAlreadyInited = TRUE;
  90. } else {
  91. bAlreadyInited = FALSE;
  92. g_hMap = CreateFileMapping(INVALID_HANDLE_VALUE,
  93. NULL,
  94. PAGE_READWRITE,
  95. 0,
  96. sizeof(VLOG_GLOBAL_DATA),
  97. szShared);
  98. }
  99. if (!g_hMap) {
  100. DPF("Cannot get shared global data.");
  101. g_bLoggingDisabled = TRUE;
  102. return FALSE;
  103. }
  104. g_pData = (PVLOG_GLOBAL_DATA)MapViewOfFile(g_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  105. if (!g_pData) {
  106. DPF("Cannot map shared global data.");
  107. g_bLoggingDisabled = TRUE;
  108. return FALSE;
  109. }
  110. if (bAlreadyInited) {
  111. if (g_pData->szProcessLog[0] == 0 || g_pData->szSessionLog[0] == 0) {
  112. g_bLoggingDisabled = TRUE;
  113. g_pData->bLoggingDisabled = TRUE;
  114. return FALSE;
  115. }
  116. g_bLoggingDisabled = g_pData->bLoggingDisabled;
  117. wcscpy(g_szSessionLog, g_pData->szSessionLog);
  118. wcscpy(g_szProcessLog, g_pData->szProcessLog);
  119. return TRUE;
  120. } else {
  121. //
  122. // just in case -- make sure these are NULL
  123. //
  124. ZeroMemory(g_pData, sizeof(VLOG_GLOBAL_DATA));
  125. }
  126. //
  127. // we need to init the file mapping, so temporarily disable logging, just in case.
  128. //
  129. g_pData->bLoggingDisabled = TRUE;
  130. //
  131. // init the CString objects
  132. //
  133. //
  134. // the verifier log will be located in %windir%\AppPatch\VLog
  135. //
  136. //
  137. // First, check that VLog exists; if not, we're not logging
  138. //
  139. GetSystemWindowsDirectoryW(szVLogPath, MAX_PATH);
  140. wcscat(szVLogPath, L"\\AppPatch\\VLog");
  141. if (GetFileAttributesW(szVLogPath) == -1) {
  142. if (!CreateDirectory(szVLogPath, NULL)) {
  143. DPF("No log directory %ls. Logging disabled.", szVLogPath);
  144. g_bLoggingDisabled = TRUE;
  145. return FALSE;
  146. }
  147. }
  148. //
  149. // Next, check for the existence of session.log. If it's not there,
  150. // we're not logging
  151. //
  152. wcscpy(g_szSessionLog, szVLogPath);
  153. wcscat(g_szSessionLog, L"\\session.log");
  154. if (GetFileAttributesW(g_szSessionLog) == -1) {
  155. hFile = CreateFile(g_szSessionLog,
  156. GENERIC_WRITE,
  157. 0,
  158. NULL,
  159. CREATE_ALWAYS,
  160. FILE_ATTRIBUTE_NORMAL,
  161. NULL);
  162. if (hFile != INVALID_HANDLE_VALUE) {
  163. CloseHandle(hFile);
  164. } else {
  165. DPF("No session log file '%ls'. Logging disabled.", g_szSessionLog);
  166. g_bLoggingDisabled = TRUE;
  167. return FALSE;
  168. }
  169. }
  170. //
  171. // get the process log file name
  172. //
  173. GetExeName(szProcessPath, szProcessName);
  174. //
  175. // combine into log name, find first available
  176. //
  177. nTemp = 0;
  178. do {
  179. swprintf(g_szProcessLog, L"%ls\\%ls%d.%ls", szVLogPath, szProcessName, nTemp, L"log");
  180. nTemp++;
  181. } while (GetFileAttributesW(g_szProcessLog) != -1);
  182. //
  183. // open the file. create it if it doesn't exist, and truncate
  184. //
  185. hFile = CreateFileW(g_szProcessLog,
  186. GENERIC_ALL,
  187. 0,
  188. NULL,
  189. CREATE_ALWAYS,
  190. FILE_ATTRIBUTE_NORMAL,
  191. NULL);
  192. if (hFile == INVALID_HANDLE_VALUE) {
  193. dwErr = GetLastError();
  194. DPF("Cannot create verifier process log file '%ls'. Error 0x%08X.",
  195. g_szProcessLog, dwErr);
  196. g_bLoggingDisabled = TRUE;
  197. return FALSE;
  198. }
  199. CloseHandle(hFile);
  200. //
  201. // put the info in the session log and the process log
  202. //
  203. g_pData->bLoggingDisabled = FALSE;
  204. g_bLoggingDisabled = FALSE;
  205. //
  206. // I realize these pointers point to process-specific memory, but since
  207. // this mapping is only shared by this process, it seems safe.
  208. //
  209. wcscpy(g_pData->szProcessLog, g_szProcessLog);
  210. wcscpy(g_pData->szSessionLog, g_szSessionLog);
  211. GetLocalTime(&LocalTime);
  212. swprintf(szTime,
  213. L"%d/%d/%d %d:%02d:%02d",
  214. LocalTime.wMonth,
  215. LocalTime.wDay,
  216. LocalTime.wYear,
  217. LocalTime.wHour,
  218. LocalTime.wMinute,
  219. LocalTime.wSecond);
  220. sprintf(szTemp,
  221. "# LOG_BEGIN %ls '%ls' '%ls'",
  222. szTime,
  223. szProcessPath,
  224. g_szProcessLog);
  225. WriteToProcessLog(szTemp);
  226. WriteToSessionLog(szTemp);
  227. //
  228. // Dump the log provider info
  229. //
  230. sprintf(szTemp, "# SHIM_BEGIN %ls 1", DEBUGGER_LOG);
  231. WriteToProcessLog(szTemp);
  232. sprintf(szTemp, "# LOGENTRY %ls 0 '%ls", DEBUGGER_LOG, DEBUGGER_ENTRY_CRASH);
  233. WriteToProcessLog(szTemp);
  234. WriteToProcessLog("# DESCRIPTION BEGIN");
  235. sprintf(szTemp, "%ls", DEBUGGER_ENTRY_CRASH_DESCRIPTION);
  236. WriteToProcessLog(szTemp);
  237. WriteToProcessLog("# DESCRIPTION END");
  238. return TRUE;
  239. }
  240. /*++
  241. Function Description:
  242. clean up all our shared file resources
  243. History:
  244. 04/26/2001 dmunsil Created
  245. --*/
  246. void
  247. ReleaseLogSupport(
  248. void
  249. )
  250. {
  251. g_bLoggingDisabled = TRUE;
  252. if (g_pData) {
  253. UnmapViewOfFile(g_pData);
  254. g_pData = NULL;
  255. if (g_hMap) {
  256. CloseHandle(g_hMap);
  257. g_hMap = NULL;
  258. }
  259. }
  260. }
  261. /*++
  262. Function Description:
  263. Logs a problem that the verifier has found
  264. History:
  265. 04/26/2001 dmunsil Created
  266. --*/
  267. void
  268. VLog(
  269. LPCSTR pszFmt,
  270. ...
  271. )
  272. {
  273. char szT[1024];
  274. char* szTemp;
  275. int nLen;
  276. int nRemain;
  277. va_list arglist;
  278. if (g_bLoggingDisabled) {
  279. return;
  280. }
  281. _snprintf(szT, 1023, "| %ls 0 '", DEBUGGER_LOG);
  282. nLen = lstrlenA(szT);
  283. szTemp = szT + nLen;
  284. nRemain = 1023 - nLen;
  285. if (nRemain > 0) {
  286. va_start(arglist, pszFmt);
  287. _vsnprintf(szTemp, nRemain, pszFmt, arglist);
  288. va_end(arglist);
  289. }
  290. szT[1023] = 0;
  291. WriteToProcessLog(szT);
  292. }
  293. /*++
  294. Function Description:
  295. Writes a line of text to the process log file
  296. Return Value:
  297. History:
  298. 04/26/2001 dmunsil Created
  299. --*/
  300. void
  301. WriteToProcessLog(
  302. LPCSTR szLine
  303. )
  304. {
  305. HANDLE hFile;
  306. DWORD bytesWritten;
  307. if (g_bLoggingDisabled) {
  308. return;
  309. }
  310. // open the log file
  311. hFile = CreateFileW(g_szProcessLog,
  312. GENERIC_WRITE,
  313. 0,
  314. NULL,
  315. OPEN_EXISTING,
  316. FILE_ATTRIBUTE_NORMAL,
  317. NULL);
  318. if (hFile == INVALID_HANDLE_VALUE) {
  319. DPF("Cannot open verifier log file '%s'", g_szProcessLog);
  320. return;
  321. }
  322. // go to the end of the file
  323. SetFilePointer(hFile, 0, NULL, FILE_END);
  324. // make sure we have no '\n' or '\r' at the end of the string.
  325. int len = lstrlenA(szLine);
  326. while (len && (szLine[len - 1] == '\n' || szLine[len - 1] == '\r')) {
  327. len--;
  328. }
  329. // write the actual log
  330. WriteFile(hFile, szLine, len, &bytesWritten, NULL);
  331. // new line
  332. WriteFile(hFile, "\r\n", 2, &bytesWritten, NULL);
  333. CloseHandle(hFile);
  334. // dump it in the debugger as well on checked builds
  335. #if DBG
  336. DPF((LPSTR)szLine);
  337. #endif // DBG
  338. }
  339. /*++
  340. Function Description:
  341. Writes a line of text to the session log file
  342. Return Value:
  343. History:
  344. 04/26/2001 dmunsil Created
  345. --*/
  346. void
  347. WriteToSessionLog(
  348. LPCSTR szLine
  349. )
  350. {
  351. HANDLE hFile;
  352. DWORD bytesWritten;
  353. if (g_bLoggingDisabled) {
  354. return;
  355. }
  356. // open the log file
  357. hFile = CreateFileW(g_szSessionLog,
  358. GENERIC_WRITE,
  359. 0,
  360. NULL,
  361. OPEN_EXISTING,
  362. FILE_ATTRIBUTE_NORMAL,
  363. NULL);
  364. if (hFile == INVALID_HANDLE_VALUE) {
  365. DPF("Cannot open verifier log file '%s'", g_szSessionLog);
  366. return;
  367. }
  368. // go to the end of the file
  369. SetFilePointer(hFile, 0, NULL, FILE_END);
  370. // make sure we have no '\n' or '\r' at the end of the string.
  371. int len = lstrlenA(szLine);
  372. while (len && (szLine[len - 1] == '\n' || szLine[len - 1] == '\r')) {
  373. len--;
  374. }
  375. // write the actual log
  376. WriteFile(hFile, szLine, len, &bytesWritten, NULL);
  377. // new line
  378. WriteFile(hFile, "\r\n", 2, &bytesWritten, NULL);
  379. CloseHandle(hFile);
  380. // dump it in the debugger as well on checked builds
  381. #if DBG
  382. DPF((LPSTR)szLine);
  383. #endif // DBG
  384. }