2004-10-24 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / tools / regtests.c
index fe9ad7f..bb29ac7 100755 (executable)
@@ -36,8 +36,6 @@ static FILE *out;
 static char *path;
 static char *file;
 static char *makefile;
-static char *umstubfile;
-static char *kmstubfile;
 static char *exestubfile;
 
 static char*
@@ -430,109 +428,11 @@ write_file_if_changed(char *filename,
   return 0;
 }
 
-static char KMSTUB[] =
-  "/* This file is autogenerated. */\n"
-  "\n"
-  "#include <roskrnl.h>\n"
-  "#include <../kmregtests/kmregtests.h>\n"
-  "\n"
-  "typedef int (*TestRoutine)(int Command, char *Buffer);\n"
-  "\n"
-  "extern void RegisterTests();\n"
-  "\n"
-  "static PDEVICE_OBJECT KMRegTestsDeviceObject = NULL;\n"
-  "static PFILE_OBJECT KMRegTestsFileObject = NULL;\n"
-  "\n"
-  "void AddTest(TestRoutine Routine)\n"
-  "{\n"
-  "  UNICODE_STRING DriverName;\n"
-  "  IO_STATUS_BLOCK IoStatus;\n"
-  "  NTSTATUS Status;\n"
-  "  KEVENT Event;\n"
-  "  PIRP Irp;\n"
-  "\n"
-  "  if (KMRegTestsDeviceObject == NULL)\n"
-  "    {\n"
-  "      RtlInitUnicodeString(&DriverName, L\"\\\\Device\\\\KMRegTests\");\n"
-  "         Status = IoGetDeviceObjectPointer(&DriverName, FILE_WRITE_ATTRIBUTES,\n"
-  "           &KMRegTestsFileObject, &KMRegTestsDeviceObject);\n"
-  "         if (!NT_SUCCESS(Status)) return;\n"
-  "       }\n"
-  "  KeInitializeEvent(&Event, NotificationEvent, FALSE);\n"
-  "  Irp = IoBuildDeviceIoControlRequest(IOCTL_KMREGTESTS_REGISTER,\n"
-  "       KMRegTestsDeviceObject, &Routine, sizeof(TestRoutine), NULL, 0, FALSE, &Event, &IoStatus);\n"
-  "  Status = IoCallDriver(KMRegTestsDeviceObject, Irp);\n"
-  "}\n"
-  "\n"
-  "void PrepareTests()\n"
-  "{\n"
-  "  RegisterTests();\n"
-  "}\n";
-
-static char UMSTUB[] =
-  "/* This file is autogenerated. */\n"
-  "\n"
-  "#include <windows.h>\n"
-  "#define NTOS_MODE_USER\n"
-  "#include <ntos.h>\n"
-  "#include \"regtests.h\"\n"
-  "\n"
-  "PVOID\n"
-  "AllocateMemory(ULONG Size)\n"
-  "{\n"
-  "  return (PVOID) RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);\n"
-  "}\n"
-  "\n"
-  "VOID\n"
-  "FreeMemory(PVOID Base)\n"
-  "{\n"
-  "  RtlFreeHeap(RtlGetProcessHeap(), 0, Base);\n"
-  "}\n"
-  "\n"
-  "/* This function will be called several times */\n"
-  "void PrepareTests()\n"
-  "{\n"
-  "  static int testsRegistered = 0;\n"
-  "  if (testsRegistered == 0)\n"
-  "    {\n"
-  "         HANDLE hEvent;\n"
-  "         hEvent = OpenEventW(\n"
-  "        EVENT_ALL_ACCESS,\n"
-  "        FALSE,\n"
-  "        L\"WinRegTests\");\n"
-  "         if (hEvent != NULL)\n"
-  "           {\n"
-  "                 SetEvent(hEvent);\n"
-  "             CloseHandle(hEvent);\n"
-  "             testsRegistered = 1;\n"
-  "          InitializeTests();\n"
-  "          RegisterTests();\n"
-  "          PerformTests(NULL, NULL);\n"
-  "        }\n"
-  "    }\n"
-  "}\n";
-
 static char EXESTUB[] =
   "/* This file is autogenerated. */\n"
   "\n"
-  "#include <stdio.h>\n"
-  "#include <windows.h>\n"
-  "#define NTOS_MODE_USER\n"
-  "#include <ntos.h>\n"
   "#include \"regtests.h\"\n"
   "\n"
-  "PVOID\n"
-  "AllocateMemory(ULONG Size)\n"
-  "{\n"
-  "  return (PVOID) RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);\n"
-  "}\n"
-  "\n"
-  "VOID\n"
-  "FreeMemory(PVOID Base)\n"
-  "{\n"
-  "  RtlFreeHeap(RtlGetProcessHeap(), 0, Base);\n"
-  "}\n"
-  "\n"
   "void\n"
   "ConsoleWrite(char *Buffer)\n"
   "{\n"
@@ -540,12 +440,16 @@ static char EXESTUB[] =
   "}\n"
   "\n"
   "int\n"
-  "main()\n"
+  "mainCRTStartup(HANDLE hInstance,\n"
+  "  HANDLE hPrevInstance,\n"
+  "  LPSTR lpszCmdParam,\n"
+  "  int nCmdShow)\n"
   "{\n"
   "  InitializeTests();\n"
   "  RegisterTests();\n"
+  "  SetupOnce();\n"
   "  PerformTests(ConsoleWrite, NULL);\n"
-  "  NtTerminateProcess (NtCurrentProcess(), 0);\n"
+  "  _ExitProcess(0);\n"
   "  return 0;\n"
   "}\n";
 
@@ -573,24 +477,16 @@ static char HOOKS_FOOTER[] =
   "};\n"
   "\n"
   "#define ExternalDependencyCount %d\n"
-  "ULONG MaxExternalDependency = ExternalDependencyCount - 1;\n"
-  "\n"
-  "PVOID STDCALL\n"
-  "FrameworkGetHook(ULONG index)\n"
-  "{\n"
-  "  return FrameworkGetHookInternal(index);\n"
-  "}\n";
+  "ULONG MaxExternalDependency = ExternalDependencyCount - 1;\n";
 
 static char HELP[] =
-  "REGTESTS path file makefile [-u umstubfile] [-k kmstubfile] [-e exestubfile]\n"
+  "REGTESTS path file makefile [-e exestubfile]\n"
   "REGTESTS -s stublistfile stubsfile hooksfile\n"
   "\n"
   "  path         Path to files\n"
   "  file         Registration file to create\n"
   "  makefile     Makefile to create\n"
-  "  umstubfile   Optional stub for running tests internal to a user-mode module\n"
-  "  kmstubfile   Optional stub for running tests internal to a kernel-mode module\n"
-  "  exestubfile  Optional stub for running tests internal to a module in the build environment\n"
+  "  exestubfile  Optional stub for running tests in the build environment\n"
   "  stublistfile File with descriptions of stubs\n"
   "  stubsfile    File with stubs to create\n"
   "  hooksfile    File with hooks to create\n";
@@ -616,7 +512,19 @@ write_hooks_footer(FILE *hooks_out, unsigned long nr_stubs)
 }
 
 char *
-get_undecorate_name(char *buf,
+get_symbolname(char *decoratedname)
+{
+  char buf[300];
+
+  if (decoratedname[0] == '@')
+    return strdup(decoratedname);
+  strcpy(buf, "_");
+  strcat(buf, decoratedname);
+  return strdup(buf);
+}
+
+char *
+get_undecorated_name(char *buf,
   char *decoratedname)
 {
   int start = 0;
@@ -639,20 +547,59 @@ get_undecorate_name(char *buf,
   return buf;
 }
 
+char *
+get_forwarded_export(char *forwardedexport)
+{
+  char buf[300];
+
+  if (forwardedexport == NULL)
+    {
+      strcpy(buf, "NULL");
+    }
+  else
+    {
+      sprintf(buf, "\"%s\"", forwardedexport);
+    }
+  return strdup(buf);
+}
+
 void
 write_stub(FILE *stubs_out, FILE *hooks_out, char *dllname,
-  char *decoratedname, unsigned int stub_index)
+  char *decoratedname_and_forward, unsigned int stub_index)
 {
   char buf[300];
+  char *p;
+  char *decoratedname = NULL;
+  char *forwardedexport = NULL;
+  char *symbolname = NULL;
+
+  p = strtok(decoratedname_and_forward, "=");
+  if (p != NULL)
+    {
+      decoratedname = p;
+
+      p = strtok(NULL, "=");
+      forwardedexport = p;
+    }
+  else
+    {
+      decoratedname = decoratedname_and_forward;
+      forwardedexport = decoratedname_and_forward;
+    }
 
-  fprintf(stubs_out, ".globl _%s\n", decoratedname);
-  fprintf(stubs_out, "_%s:\n", decoratedname);
+  symbolname = get_symbolname(decoratedname);
+  fprintf(stubs_out, ".globl %s\n", symbolname);
+  fprintf(stubs_out, "%s:\n", symbolname);
+  free(symbolname);
   fprintf(stubs_out, "  pushl $%d\n", stub_index);
   fprintf(stubs_out, "  jmp passthrough\n");
   fprintf(stubs_out, "\n");
-
-  fprintf(hooks_out, "  {\"%s\", \"%s\", NULL, NULL},\n",
-    dllname, get_undecorate_name(buf, decoratedname));
+  forwardedexport = get_forwarded_export(forwardedexport);
+  fprintf(hooks_out, "  {\"%s\", \"%s\", %s, NULL, NULL},\n",
+    dllname,
+    get_undecorated_name(buf, decoratedname),
+    forwardedexport);
+  free(forwardedexport);
 }
 
 void
@@ -664,7 +611,7 @@ create_stubs_and_hooks(
   char line[INPUT_BUFFER_SIZE];
   char *s;
   char *dllname;
-  char *decoratedname;
+  char *decoratedname_and_forward;
   int stub_index;
 
   write_stubs_header(stubs_out);
@@ -679,13 +626,14 @@ create_stubs_and_hooks(
         * DLLNAME (e.g. ntdll.dll)
         * DECORATED NAME (e.g. NtCreateProcess@32, @InterlockedIncrement@4 or printf)
         */
+  stub_index = 0; /* First stub has index zero */
+
        for (
-    /* First stub has index zero */
-               stub_index = 0;
+    ;
                /* Go on until EOF or read zero bytes */
                ((!feof(in)) && (fgets(line, sizeof line, in) != NULL));
                /* Next stub index */
-         stub_index++)
+         )
        {
                /*
                 * Remove, if present, the trailing LF.
@@ -709,16 +657,24 @@ create_stubs_and_hooks(
                s = & line[0];
                if ((*s) != '#' && (*s) != '\0')
                {
-                       /* Extract the DLL name */
-                       dllname = (char *) strtok(s," \t");
-                       /* Extract the decorated function name */
-                       decoratedname = (char *) strtok(NULL," \t");
-                       /* Extract the argument count */
-                       write_stub(stubs_out, hooks_out, dllname, decoratedname, stub_index);
+        /* Extract the DLL name */
+        dllname = (char *) strtok(s, " \t");
+        if (dllname != NULL && strlen(dllname) > 0)
+          {
+                         /*
+             * Extract the decorated function name and possibly forwarded export.
+             * Format:
+             *   decoratedname=forwardedexport (no DLL name)
+             */
+                 decoratedname_and_forward = (char *) strtok(NULL, " \t");
+                           /* Extract the argument count */
+                           write_stub(stubs_out, hooks_out, dllname, decoratedname_and_forward, stub_index);
+            stub_index++;
+          }
                }
        }
 
-  write_hooks_footer(hooks_out, stub_index + 1);
+  write_hooks_footer(hooks_out, stub_index);
 }
 
 int run_stubs(int argc,
@@ -797,45 +753,25 @@ int run_registrations(int argc,
       return 1;
     }
 
-  umstubfile = NULL;
-  kmstubfile = NULL;
   exestubfile = NULL;
   for (i = 4; i < argc; i++)
     {
          if (argv[i][0] == '-')
            {
-             if (argv[i][1] == 'u')
-                   {
-              umstubfile = convert_path(argv[++i]);
-              if (umstubfile[0] == 0)
-                {
-                  printf("Missing umstubfile\n");
-                  return 1;
-                }
-                   }
-                 else if (argv[i][1] == 'k')
-                   {
-              kmstubfile = convert_path(argv[++i]);
-              if (kmstubfile[0] == 0)
-                {
-                  printf("Missing kmstubfile\n");
-                  return 1;
-                }
-                   }
-                 else if (argv[i][1] == 'e')
-                   {
-              exestubfile = convert_path(argv[++i]);
-              if (exestubfile[0] == 0)
-                {
-                  printf("Missing exestubfile\n");
-                  return 1;
-                }
-                   }
-                 else
-                   {
-              printf("Unknown switch\n");
-              return 1;
-                   }
+        if (argv[i][1] == 'e')
+                   {
+            exestubfile = convert_path(argv[++i]);
+            if (exestubfile[0] == 0)
+              {
+                printf("Missing exestubfile\n");
+                return 1;
+              }
+                   }
+                 else
+                   {
+                printf("Unknown switch -%c\n", argv[i][1]);
+                return 1;
+                   }
            }
         }
 
@@ -886,26 +822,6 @@ int run_registrations(int argc,
 
   fclose(out);
 
-  /* User-mode stubfile */
-  if (umstubfile != NULL)
-    {
-      if (write_file_if_changed(umstubfile, UMSTUB) != 0)
-        {
-          perror("Cannot create output user-mode stubfile");
-          return 1;
-        }
-    }
-
-  /* Kernel-mode stubfile */
-  if (kmstubfile != NULL)
-    {
-      if (write_file_if_changed(kmstubfile, KMSTUB) != 0)
-        {
-          perror("Cannot create output kernel-mode stubfile");
-          return 1;
-        }
-    }
-
   /* Executable stubfile */
   if (exestubfile != NULL)
     {