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.

614 lines
16 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. process.c
  5. Abstract:
  6. This module maintains state about each process/thread created by the application
  7. setup/install program.
  8. Author:
  9. Steve Wood (stevewo) 09-Aug-1994
  10. Revision History:
  11. --*/
  12. #include "instaler.h"
  13. BOOLEAN
  14. AddProcess(
  15. LPDEBUG_EVENT DebugEvent,
  16. PPROCESS_INFO *ReturnedProcess
  17. )
  18. {
  19. NTSTATUS Status;
  20. PPROCESS_INFO Process;
  21. RTL_USER_PROCESS_PARAMETERS ProcessParameters;
  22. PEB Peb;
  23. PWSTR FreeBuffer, s;
  24. Process = AllocMem( sizeof( *Process ) );
  25. if (Process == NULL) {
  26. return FALSE;
  27. }
  28. Process->Id = DebugEvent->dwProcessId;
  29. Process->Handle = DebugEvent->u.CreateProcessInfo.hProcess;
  30. InitializeListHead( &Process->ThreadListHead );
  31. InitializeListHead( &Process->BreakpointListHead );
  32. InitializeListHead( &Process->OpenHandleListHead );
  33. InsertTailList( &ProcessListHead, &Process->Entry );
  34. *ReturnedProcess = Process;
  35. Status = NtQueryInformationProcess( Process->Handle,
  36. ProcessBasicInformation,
  37. &Process->ProcessInformation,
  38. sizeof( Process->ProcessInformation ),
  39. NULL
  40. );
  41. FreeBuffer = NULL;
  42. if (ReadMemory( Process,
  43. Process->ProcessInformation.PebBaseAddress,
  44. &Peb,
  45. sizeof( Peb ),
  46. "PEB"
  47. ) &&
  48. Peb.ProcessParameters != NULL &&
  49. ReadMemory( Process,
  50. Peb.ProcessParameters,
  51. &ProcessParameters,
  52. sizeof( ProcessParameters ),
  53. "ProcessParameters"
  54. ) &&
  55. ProcessParameters.ImagePathName.Length != 0 &&
  56. (FreeBuffer = AllocMem( ProcessParameters.ImagePathName.Length + sizeof( UNICODE_NULL ) )) != NULL &&
  57. ReadMemory( Process,
  58. ProcessParameters.Flags & RTL_USER_PROC_PARAMS_NORMALIZED ?
  59. ProcessParameters.ImagePathName.Buffer :
  60. (PWSTR)((ULONG)(ProcessParameters.ImagePathName.Buffer) + (PCHAR)(Peb.ProcessParameters)),
  61. FreeBuffer,
  62. ProcessParameters.ImagePathName.Length,
  63. "Image File Name"
  64. )
  65. ) {
  66. s = (PWSTR)((PCHAR)FreeBuffer + ProcessParameters.ImagePathName.Length);
  67. while (s > FreeBuffer && s[ -1 ] != OBJ_NAME_PATH_SEPARATOR) {
  68. s--;
  69. }
  70. wcsncpy( Process->ImageFileName,
  71. s,
  72. (sizeof( Process->ImageFileName ) - sizeof( UNICODE_NULL )) / sizeof( WCHAR )
  73. );
  74. //
  75. // BogdanA 02/28/2002 : make sure we NULL terminate the buffer
  76. //
  77. Process->ImageFileName[(sizeof( Process->ImageFileName ) - sizeof( UNICODE_NULL )) / sizeof( WCHAR )] = UNICODE_NULL;
  78. }
  79. FreeMem( &FreeBuffer );
  80. return TRUE;
  81. }
  82. BOOLEAN
  83. DeleteProcess(
  84. PPROCESS_INFO Process
  85. )
  86. {
  87. PLIST_ENTRY Next, Head;
  88. PTHREAD_INFO Thread;
  89. PBREAKPOINT_INFO Breakpoint;
  90. POPENHANDLE_INFO p;
  91. RemoveEntryList( &Process->Entry );
  92. Head = &Process->ThreadListHead;
  93. Next = Head->Flink;
  94. while (Next != Head) {
  95. Thread = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
  96. Next = Next->Flink;
  97. DeleteThread( Process, Thread );
  98. }
  99. Head = &Process->BreakpointListHead;
  100. Next = Head->Flink;
  101. while (Next != Head) {
  102. Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
  103. Next = Next->Flink;
  104. DestroyBreakpoint( Breakpoint->Address, Process, NULL );
  105. }
  106. Head = &Process->OpenHandleListHead;
  107. Next = Head->Flink;
  108. while (Next != Head) {
  109. p = CONTAINING_RECORD( Next, OPENHANDLE_INFO, Entry );
  110. Next = Next->Flink;
  111. DeleteOpenHandle( Process, p->Handle, p->Type );
  112. }
  113. FreeMem( &Process );
  114. return TRUE;
  115. }
  116. BOOLEAN
  117. AddThread(
  118. LPDEBUG_EVENT DebugEvent,
  119. PPROCESS_INFO Process,
  120. PTHREAD_INFO *ReturnedThread
  121. )
  122. {
  123. PTHREAD_INFO Thread;
  124. Thread = AllocMem( sizeof( *Thread ) );
  125. if (Thread == NULL) {
  126. return FALSE;
  127. }
  128. Thread->Id = DebugEvent->dwThreadId;
  129. if (DebugEvent->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
  130. Thread->Handle = DebugEvent->u.CreateProcessInfo.hThread;
  131. Thread->StartAddress = DebugEvent->u.CreateProcessInfo.lpStartAddress;
  132. }
  133. else {
  134. Thread->Handle = DebugEvent->u.CreateThread.hThread;
  135. Thread->StartAddress = DebugEvent->u.CreateThread.lpStartAddress;
  136. }
  137. Thread->SingleStepExpected = FALSE;
  138. InitializeListHead( &Thread->BreakpointListHead );
  139. InsertTailList( &Process->ThreadListHead, &Thread->Entry );
  140. *ReturnedThread = Thread;
  141. return TRUE;
  142. }
  143. BOOLEAN
  144. DeleteThread(
  145. PPROCESS_INFO Process,
  146. PTHREAD_INFO Thread
  147. )
  148. {
  149. PLIST_ENTRY Next, Head;
  150. PBREAKPOINT_INFO Breakpoint;
  151. RemoveEntryList( &Thread->Entry );
  152. Head = &Thread->BreakpointListHead;
  153. Next = Head->Flink;
  154. while (Next != Head) {
  155. Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
  156. Next = Next->Flink;
  157. DestroyBreakpoint( Breakpoint->Address, Process, Thread );
  158. }
  159. FreeMem( &Thread );
  160. return TRUE;
  161. }
  162. PPROCESS_INFO
  163. FindProcessById(
  164. ULONG Id
  165. )
  166. {
  167. PLIST_ENTRY Next, Head;
  168. PPROCESS_INFO Process;
  169. Head = &ProcessListHead;
  170. Next = Head->Flink;
  171. while (Next != Head) {
  172. Process = CONTAINING_RECORD( Next, PROCESS_INFO, Entry );
  173. if (Process->Id == Id) {
  174. return Process;
  175. }
  176. Next = Next->Flink;
  177. }
  178. return NULL;
  179. }
  180. BOOLEAN
  181. FindProcessAndThreadForEvent(
  182. LPDEBUG_EVENT DebugEvent,
  183. PPROCESS_INFO *ReturnedProcess,
  184. PTHREAD_INFO *ReturnedThread
  185. )
  186. {
  187. PLIST_ENTRY Next, Head;
  188. PPROCESS_INFO Process;
  189. PTHREAD_INFO Thread;
  190. Head = &ProcessListHead;
  191. Next = Head->Flink;
  192. Process = NULL;
  193. Thread = NULL;
  194. while (Next != Head) {
  195. Process = CONTAINING_RECORD( Next, PROCESS_INFO, Entry );
  196. if (Process->Id == DebugEvent->dwProcessId) {
  197. Head = &Process->ThreadListHead;
  198. Next = Head->Flink;
  199. while (Next != Head) {
  200. Thread = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
  201. if (Thread->Id == DebugEvent->dwThreadId) {
  202. break;
  203. }
  204. Thread = NULL;
  205. Next = Next->Flink;
  206. }
  207. break;
  208. }
  209. Process = NULL;
  210. Next = Next->Flink;
  211. }
  212. *ReturnedProcess = Process;
  213. *ReturnedThread = Thread;
  214. if (DebugEvent->dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
  215. if (Process != NULL) {
  216. DeclareError( INSTALER_DUPLICATE_PROCESS_ID, 0, DebugEvent->dwProcessId );
  217. return FALSE;
  218. }
  219. }
  220. else
  221. if (DebugEvent->dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT) {
  222. if (Thread != NULL) {
  223. DeclareError( INSTALER_DUPLICATE_THREAD_ID, 0, DebugEvent->dwThreadId, DebugEvent->dwProcessId );
  224. return FALSE;
  225. }
  226. if (Process == NULL) {
  227. DeclareError( INSTALER_MISSING_PROCESS_ID, 0, DebugEvent->dwProcessId );
  228. return FALSE;
  229. }
  230. }
  231. else
  232. if (Process == NULL) {
  233. DeclareError( INSTALER_MISSING_PROCESS_ID, 0, DebugEvent->dwProcessId );
  234. return FALSE;
  235. }
  236. else
  237. if (Thread == NULL) {
  238. DeclareError( INSTALER_MISSING_THREAD_ID, 0, DebugEvent->dwThreadId, DebugEvent->dwProcessId );
  239. return FALSE;
  240. }
  241. return TRUE;
  242. }
  243. VOID
  244. SuspendAllButThisThread(
  245. PPROCESS_INFO Process,
  246. PTHREAD_INFO Thread
  247. )
  248. {
  249. PTHREAD_INFO Thread1;
  250. PLIST_ENTRY Next, Head;
  251. if (Thread != NULL) {
  252. Head = &Process->ThreadListHead;
  253. Next = Head->Flink;
  254. while (Next != Head) {
  255. Thread1 = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
  256. if (Thread1 != Thread) {
  257. NtSuspendThread( Thread1->Handle, NULL );
  258. }
  259. Next = Next->Flink;
  260. }
  261. }
  262. return;
  263. }
  264. VOID
  265. ResumeAllButThisThread(
  266. PPROCESS_INFO Process,
  267. PTHREAD_INFO Thread
  268. )
  269. {
  270. PTHREAD_INFO Thread1;
  271. PLIST_ENTRY Next, Head;
  272. if (Thread != NULL) {
  273. Head = &Process->ThreadListHead;
  274. Next = Head->Flink;
  275. while (Next != Head) {
  276. Thread1 = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
  277. if (Thread1 != Thread) {
  278. NtResumeThread( Thread1->Handle, NULL );
  279. }
  280. Next = Next->Flink;
  281. }
  282. }
  283. return;
  284. }
  285. PBREAKPOINT_INFO
  286. FindBreakpoint(
  287. LPVOID Address,
  288. PPROCESS_INFO Process,
  289. PTHREAD_INFO Thread
  290. )
  291. {
  292. PBREAKPOINT_INFO Breakpoint;
  293. PLIST_ENTRY Next, Head;
  294. if (Thread != NULL) {
  295. Head = &Thread->BreakpointListHead;
  296. Next = Head->Flink;
  297. while (Next != Head) {
  298. Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
  299. if (Breakpoint->Address == Address) {
  300. return Breakpoint;
  301. }
  302. Next = Next->Flink;
  303. }
  304. }
  305. Head = &Process->BreakpointListHead;
  306. Next = Head->Flink;
  307. while (Next != Head) {
  308. Breakpoint = CONTAINING_RECORD( Next, BREAKPOINT_INFO, Entry );
  309. if (Breakpoint->Address == Address) {
  310. return Breakpoint;
  311. }
  312. Next = Next->Flink;
  313. }
  314. return NULL;
  315. }
  316. BOOLEAN
  317. CreateBreakpoint(
  318. LPVOID Address,
  319. PPROCESS_INFO Process,
  320. PTHREAD_INFO Thread,
  321. UCHAR ApiIndex,
  322. PAPI_SAVED_PARAMETERS SavedParameters,
  323. PBREAKPOINT_INFO *ReturnedBreakpoint
  324. )
  325. {
  326. PBREAKPOINT_INFO Breakpoint;
  327. Breakpoint = FindBreakpoint( Address, Process, Thread );
  328. if (ARGUMENT_PRESENT( ReturnedBreakpoint )) {
  329. *ReturnedBreakpoint = Breakpoint;
  330. }
  331. if (Breakpoint != NULL) {
  332. return (Breakpoint->ApiIndex == ApiIndex);
  333. }
  334. Breakpoint = AllocMem( sizeof( *Breakpoint ) );
  335. if (Breakpoint == NULL) {
  336. return FALSE;
  337. }
  338. Breakpoint->Address = Address;
  339. Breakpoint->ApiIndex = ApiIndex;
  340. if (ARGUMENT_PRESENT( SavedParameters )) {
  341. Breakpoint->SavedParameters = *SavedParameters;
  342. Breakpoint->SavedParametersValid = TRUE;
  343. }
  344. else {
  345. Breakpoint->SavedParametersValid = FALSE;
  346. }
  347. if (Thread != NULL) {
  348. InsertTailList( &Thread->BreakpointListHead, &Breakpoint->Entry );
  349. }
  350. else {
  351. InsertTailList( &Process->BreakpointListHead, &Breakpoint->Entry );
  352. }
  353. InstallBreakpoint( Process, Breakpoint );
  354. if (ARGUMENT_PRESENT( ReturnedBreakpoint )) {
  355. *ReturnedBreakpoint = Breakpoint;
  356. }
  357. return TRUE;
  358. }
  359. BOOLEAN
  360. DestroyBreakpoint(
  361. LPVOID Address,
  362. PPROCESS_INFO Process,
  363. PTHREAD_INFO Thread
  364. )
  365. {
  366. PBREAKPOINT_INFO Breakpoint;
  367. Breakpoint = FindBreakpoint( Address, Process, Thread );
  368. if (Breakpoint == NULL) {
  369. return FALSE;
  370. }
  371. RemoveBreakpoint( Process, Breakpoint );
  372. RemoveEntryList( &Breakpoint->Entry );
  373. FreeMem( &Breakpoint );
  374. return TRUE;
  375. }
  376. BOOLEAN
  377. HandleThreadsForSingleStep(
  378. PPROCESS_INFO Process,
  379. PTHREAD_INFO ThreadToSingleStep,
  380. BOOLEAN SuspendThreads
  381. )
  382. {
  383. PLIST_ENTRY Next, Head;
  384. PTHREAD_INFO Thread;
  385. Head = &Process->ThreadListHead;
  386. Next = Head->Flink;
  387. while (Next != Head) {
  388. Thread = CONTAINING_RECORD( Next, THREAD_INFO, Entry );
  389. if (Thread != ThreadToSingleStep) {
  390. if (SuspendThreads) {
  391. if (Thread->BreakpointToStepOver == NULL) {
  392. SuspendThread( Thread->Handle );
  393. }
  394. }
  395. else {
  396. ResumeThread( Thread->Handle );
  397. }
  398. break;
  399. }
  400. Next = Next->Flink;
  401. }
  402. return TRUE;
  403. }
  404. BOOLEAN
  405. ReadMemory(
  406. PPROCESS_INFO Process,
  407. PVOID Address,
  408. PVOID DataRead,
  409. ULONG BytesToRead,
  410. PCHAR Reason
  411. )
  412. {
  413. ULONG BytesRead;
  414. if (!ReadProcessMemory( Process->Handle,
  415. Address,
  416. DataRead,
  417. BytesToRead,
  418. &BytesRead
  419. ) ||
  420. BytesRead != BytesToRead
  421. ) {
  422. DbgEvent( MEMORYERROR, ( "Read memory from %x for %x bytes failed (%u) - '%s'\n",
  423. Address,
  424. BytesToRead,
  425. GetLastError(),
  426. Reason
  427. )
  428. );
  429. return FALSE;
  430. }
  431. else {
  432. return TRUE;
  433. }
  434. }
  435. BOOLEAN
  436. WriteMemory(
  437. PPROCESS_INFO Process,
  438. PVOID Address,
  439. PVOID DataToWrite,
  440. ULONG BytesToWrite,
  441. PCHAR Reason
  442. )
  443. {
  444. ULONG BytesWritten;
  445. ULONG OldProtection;
  446. BOOLEAN Result;
  447. if (WriteProcessMemory( Process->Handle,
  448. Address,
  449. DataToWrite,
  450. BytesToWrite,
  451. &BytesWritten
  452. ) &&
  453. BytesWritten == BytesToWrite
  454. ) {
  455. return TRUE;
  456. }
  457. Result = FALSE;
  458. if (GetLastError() == ERROR_NOACCESS &&
  459. VirtualProtectEx( Process->Handle,
  460. Address,
  461. BytesToWrite,
  462. PAGE_READWRITE,
  463. &OldProtection
  464. )
  465. ) {
  466. if (WriteProcessMemory( Process->Handle,
  467. Address,
  468. DataToWrite,
  469. BytesToWrite,
  470. &BytesWritten
  471. ) &&
  472. BytesWritten == BytesToWrite
  473. ) {
  474. Result = TRUE;
  475. }
  476. VirtualProtectEx( Process->Handle,
  477. Address,
  478. BytesToWrite,
  479. OldProtection,
  480. &OldProtection
  481. );
  482. if (Result) {
  483. return TRUE;
  484. }
  485. }
  486. DbgEvent( MEMORYERROR, ( "Write memory to %x for %x bytes failed (%u) - '%s'\n",
  487. Address,
  488. BytesToWrite,
  489. GetLastError(),
  490. Reason
  491. )
  492. );
  493. return FALSE;
  494. }
  495. PVOID
  496. AllocMem(
  497. ULONG Size
  498. )
  499. {
  500. PVOID p;
  501. p = HeapAlloc( AppHeap, HEAP_ZERO_MEMORY, Size );
  502. if (p == NULL) {
  503. DbgEvent( INTERNALERROR, ( "HeapAlloc( %0x8 ) failed\n", Size ) );
  504. }
  505. return p;
  506. }
  507. VOID
  508. FreeMem(
  509. PVOID *p
  510. )
  511. {
  512. if (*p != NULL) {
  513. HeapFree( AppHeap, 0, *p );
  514. *p = NULL;
  515. }
  516. return;
  517. }