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.

486 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. pipe.c
  5. Abstract:
  6. Implements IPC pipe to support migisol.exe.
  7. Author:
  8. Jim Schmidt (jimschm) 21-Sept-1998
  9. Revision History:
  10. <full name> (<alias>) <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. HANDLE g_hHeap;
  14. HINSTANCE g_hInst;
  15. static PCTSTR g_Mode;
  16. static HANDLE g_ProcessHandle;
  17. static BOOL g_Host;
  18. VOID
  19. pCloseIpcData (
  20. VOID
  21. );
  22. BOOL
  23. pOpenIpcData (
  24. VOID
  25. );
  26. BOOL
  27. pCreateIpcData (
  28. IN PSECURITY_ATTRIBUTES psa
  29. );
  30. BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
  31. VOID
  32. pTestPipeMechanism (
  33. VOID
  34. );
  35. BOOL
  36. pCallEntryPoints (
  37. DWORD Reason
  38. )
  39. {
  40. HINSTANCE Instance;
  41. //
  42. // Simulate DllMain
  43. //
  44. Instance = g_hInst;
  45. //
  46. // Initialize the common libs
  47. //
  48. if (!MigUtil_Entry (Instance, Reason, NULL)) {
  49. return FALSE;
  50. }
  51. return TRUE;
  52. }
  53. BOOL
  54. Init (
  55. VOID
  56. )
  57. {
  58. g_hHeap = GetProcessHeap();
  59. g_hInst = GetModuleHandle (NULL);
  60. return pCallEntryPoints (DLL_PROCESS_ATTACH);
  61. }
  62. VOID
  63. Terminate (
  64. VOID
  65. )
  66. {
  67. pCallEntryPoints (DLL_PROCESS_DETACH);
  68. }
  69. VOID
  70. HelpAndExit (
  71. VOID
  72. )
  73. {
  74. //
  75. // This routine is called whenever command line args are wrong
  76. //
  77. _ftprintf (
  78. stderr,
  79. TEXT("Command Line Syntax:\n\n")
  80. TEXT(" pipe/F:file]\n")
  81. TEXT("\nDescription:\n\n")
  82. TEXT(" PIPE is a test tool of the IPC mechanism for migration\n")
  83. TEXT(" DLLs.\n")
  84. TEXT("\nArguments:\n\n")
  85. TEXT(" (none)\n")
  86. );
  87. exit (1);
  88. }
  89. OUR_CRITICAL_SECTION g_cs;
  90. CHAR g_Buf[2048];
  91. VOID
  92. Dump (
  93. PCSTR Str
  94. )
  95. {
  96. EnterOurCriticalSection (&g_cs);
  97. printf ("%s\n", Str);
  98. LeaveOurCriticalSection (&g_cs);
  99. }
  100. INT
  101. __cdecl
  102. _tmain (
  103. INT argc,
  104. PCTSTR argv[]
  105. )
  106. {
  107. INT i;
  108. PCTSTR FileArg;
  109. InitializeOurCriticalSection (&g_cs);
  110. for (i = 1 ; i < argc ; i++) {
  111. if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) {
  112. switch (_totlower (_tcsnextc (&argv[i][1]))) {
  113. case TEXT('f'):
  114. //
  115. // Sample option - /f:file
  116. //
  117. if (argv[i][2] == TEXT(':')) {
  118. FileArg = &argv[i][3];
  119. } else if (i + 1 < argc) {
  120. FileArg = argv[++i];
  121. } else {
  122. HelpAndExit();
  123. }
  124. break;
  125. default:
  126. HelpAndExit();
  127. }
  128. } else {
  129. //
  130. // Parse other args that don't require / or -
  131. //
  132. // None
  133. HelpAndExit();
  134. }
  135. }
  136. //
  137. // Begin processing
  138. //
  139. if (!Init()) {
  140. return 0;
  141. }
  142. pTestPipeMechanism();
  143. //
  144. // End of processing
  145. //
  146. Terminate();
  147. return 0;
  148. }
  149. BOOL
  150. pOpenIpcA (
  151. IN BOOL Win95Side,
  152. IN PCSTR ExePath, OPTIONAL
  153. IN PCSTR MigrationDllPath, OPTIONAL
  154. IN PCSTR WorkingDir OPTIONAL
  155. )
  156. /*++
  157. Routine Description:
  158. OpenIpc has two modes of operation, depending on who the caller is. If the
  159. caller is w95upg.dll or w95upgnt.dll, then the IPC mode is called "host mode."
  160. If the caller is migisol.exe, then the IPC mode is called "remote mode."
  161. In host mode, OpenIpc creates all of the objects necessary to implement
  162. the IPC. This includes two events, DoCommand and GetResults, and a
  163. file mapping. After creating the objects, the remote process is launched.
  164. In remote mode, OpenIpc opens the existing objects that have already
  165. been created.
  166. Arguments:
  167. Win95Side - Used in host mode only. Specifies that w95upg.dll is running
  168. when TRUE, or that w95upgnt.dll is running when FALSE.
  169. ExePath - Specifies the command line for migisol.exe. Specifies NULL
  170. to indicate remote mode.
  171. MigrationDllPath - Used in host mode only. Specifies the migration DLL
  172. path. Ignored in remote mode.
  173. WorkingDir - Used in host mode only. Specifies the working directory path
  174. for the migration DLL. Ignored in remote mode.
  175. Return value:
  176. TRUE if the IPC channel was opened. If host mode, TRUE indicates that
  177. migisol.exe is up and running. If remote mode, TRUE indicates that
  178. migisol is ready for commands.
  179. --*/
  180. {
  181. CHAR CmdLine[MAX_CMDLINE];
  182. STARTUPINFOA si;
  183. PROCESS_INFORMATION pi;
  184. BOOL ProcessResult;
  185. HANDLE SyncEvent = NULL;
  186. HANDLE ObjectArray[2];
  187. DWORD rc;
  188. PSECURITY_DESCRIPTOR psd = NULL;
  189. SECURITY_ATTRIBUTES sa, *psa;
  190. BOOL Result = FALSE;
  191. #ifdef DEBUG
  192. g_Mode = ExePath ? TEXT("host") : TEXT("remote");
  193. #endif
  194. __try {
  195. g_ProcessHandle = NULL;
  196. g_Host = (ExePath != NULL);
  197. if (ISNT()) {
  198. //
  199. // Create nul DACL for NT
  200. //
  201. ZeroMemory (&sa, sizeof (sa));
  202. psd = (PSECURITY_DESCRIPTOR) MemAlloc (g_hHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
  203. if (!InitializeSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION)) {
  204. __leave;
  205. }
  206. if (!SetSecurityDescriptorDacl (psd, TRUE, (PACL) NULL, FALSE)) {
  207. __leave;
  208. }
  209. sa.nLength = sizeof (sa);
  210. sa.lpSecurityDescriptor = psd;
  211. psa = &sa;
  212. } else {
  213. psa = NULL;
  214. }
  215. if (g_Host) {
  216. //
  217. // Create the IPC objects
  218. //
  219. if (!pCreateIpcData (psa)) {
  220. DEBUGMSG ((DBG_ERROR, "Cannot create IPC channel"));
  221. __leave;
  222. }
  223. g_ProcessHandle = CreateEvent (NULL, TRUE, TRUE, NULL);
  224. } else { // !g_Host
  225. //
  226. // Open the IPC objects
  227. //
  228. if (!pOpenIpcData()) {
  229. DEBUGMSG ((DBG_ERROR, "Cannot open IPC channel"));
  230. __leave;
  231. }
  232. //
  233. // Set event notifying setup that we've created our mailslot
  234. //
  235. SyncEvent = OpenEvent (EVENT_ALL_ACCESS, FALSE, TEXT("win9xupg"));
  236. SetEvent (SyncEvent);
  237. }
  238. Result = TRUE;
  239. }
  240. __finally {
  241. //
  242. // Cleanup code
  243. //
  244. PushError();
  245. if (!Result) {
  246. CloseIpc();
  247. }
  248. if (SyncEvent) {
  249. CloseHandle (SyncEvent);
  250. }
  251. if (psd) {
  252. MemFree (g_hHeap, 0, psd);
  253. }
  254. PopError();
  255. }
  256. return Result;
  257. }
  258. DWORD
  259. WINAPI
  260. pHostThread (
  261. PVOID Arg
  262. )
  263. {
  264. CHAR Buf[2048];
  265. PBYTE Data;
  266. DWORD DataSize;
  267. DWORD ResultCode;
  268. DWORD LogId;
  269. DWORD LogId2;
  270. BOOL b;
  271. if (pOpenIpcA (FALSE, TEXT("*"), TEXT("*"), TEXT("*"))) {
  272. Dump ("Host: SendIpcCommand");
  273. StringCopyA (Buf, "This is a test command");
  274. b = SendIpcCommand (IPC_QUERY, Buf, SizeOfString (Buf));
  275. wsprintfA (g_Buf, "Host: b=%u rc=%u", b, GetLastError());
  276. Dump (g_Buf);
  277. Dump ("Host: GetIpcCommandResults");
  278. b = GetIpcCommandResults (15000, &Data, &DataSize, &ResultCode, &LogId, &LogId2);
  279. wsprintfA (
  280. g_Buf,
  281. "Host: b=%u rc=%u\n"
  282. " Data=%s\n"
  283. " DataSize=%u\n"
  284. " ResultCode=%u\n"
  285. " LogId=%u\n",
  286. b,
  287. GetLastError(),
  288. Data,
  289. DataSize,
  290. ResultCode,
  291. LogId
  292. );
  293. Dump (g_Buf);
  294. } else {
  295. Dump ("Host: CreateIpcData failed!");
  296. }
  297. return 0;
  298. }
  299. DWORD
  300. WINAPI
  301. pRemoteThread (
  302. PVOID Arg
  303. )
  304. {
  305. CHAR Buf[2048];
  306. PBYTE Data;
  307. DWORD DataSize;
  308. DWORD Command;
  309. BOOL b;
  310. Sleep (1000);
  311. if (pOpenIpcA (FALSE, NULL, NULL, NULL)) {
  312. Dump ("Remote: GetIpcCommand");
  313. b = GetIpcCommand (15000, &Command, &Data, &DataSize);
  314. wsprintfA (
  315. g_Buf,
  316. "Remote: b=%u rc=%u\n"
  317. " Data=%s\n"
  318. " DataSize=%u\n"
  319. " Command=%u\n",
  320. b,
  321. GetLastError(),
  322. Data,
  323. DataSize,
  324. Command
  325. );
  326. Dump (g_Buf);
  327. Dump ("Remote: SendIpcCommandResults");
  328. StringCopyA (Buf, "Results are positive!");
  329. b = SendIpcCommandResults (ERROR_SUCCESS, 100, 0, Buf, SizeOfString (Buf));
  330. wsprintfA (g_Buf, "Remote: b=%u rc=%u", b, GetLastError());
  331. Dump (g_Buf);
  332. } else {
  333. Dump ("Remote: OpenIpcData failed!");
  334. }
  335. return 0;
  336. }
  337. VOID
  338. pTestPipeMechanism (
  339. VOID
  340. )
  341. {
  342. HANDLE Threads[2];
  343. Threads[0] = StartThread (pHostThread, NULL);
  344. Threads[1] = StartThread (pRemoteThread, NULL);
  345. WaitForMultipleObjects (2, Threads, TRUE, INFINITE);
  346. }