Panda3D
p3dWrapper.c
1 /* Filename: p3dWrapper.c
2  * Created by: rdb (16Jan10)
3  *
4  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
5  *
6  * PANDA 3D SOFTWARE
7  * Copyright (c) Carnegie Mellon University. All rights reserved.
8  *
9  * All use of this software is subject to the terms of the revised BSD
10  * license. You should have received a copy of this license along
11  * with this source code in a file named "LICENSE."
12  *
13  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
14 
15 /* p3dWrapper is a small wrapper executable that locates a .p3d file
16  in the same directory as this executable file, with the same name
17  (except .p3d instead of .exe of course). It is only meant to be
18  used on Windows system, it is not needed on Unix-like systems. */
19 
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <windows.h>
24 #include <process.h>
25 #include <assert.h>
26 #include <malloc.h>
27 
28 #define BUFFER_SIZE 1024
29 
30 /* It makes sense to use "App Paths\panda3d.exe". However, Microsoft
31  decided in their infinite wisdom to disable Redirection for that
32  key from Windows 7 onward, so we can't rely on it producing a
33  result appropriate to the right architecture when both the 32-bit
34  and 64-bit versions of the runtime are installed. Beh. */
35 
36 #define UNINST_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Panda3D Game Engine"
37 
38 int main (int argc, char* argv[]) {
39  int i;
40  char buffer[BUFFER_SIZE];
41  char* p3dfile;
42  char* runtime = NULL;
43  DWORD size;
44  STARTUPINFO si;
45  PROCESS_INFORMATION pi;
46  char *cmd;
47  char *newcmd;
48  HKEY hKey = 0;
49  char buf[1024] = {0};
50  DWORD dwType = REG_SZ;
51  DWORD dwBufSize = sizeof(buf);
52  size = GetModuleFileName(NULL, buffer, BUFFER_SIZE);
53  assert (size > 0);
54 
55  /* Chop off the .exe and replace it by .p3d. */
56  p3dfile = (char*) _alloca(size + 1);
57  memcpy(p3dfile, buffer, size);
58  p3dfile[size] = 0;
59  memcpy(p3dfile + size - 3, "p3d", 3);
60 
61  /* Find the location of panda3d.exe using the registry path. */
62 #ifdef _WIN64
63  /* If we're on 64-bit Windows, try the 64-bit registry first. */
64  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, UNINST_KEY, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS) {
65  if (RegQueryValueEx(hKey, "DisplayIcon", 0, &dwType, (BYTE*) buf, &dwBufSize) == ERROR_SUCCESS) {
66  char *slash = strrchr(buf, '\\');
67  if (slash != NULL) {
68  strcpy(slash, "\\panda3d.exe");
69  runtime = buf;
70  }
71  }
72  RegCloseKey(hKey);
73  }
74 #endif
75 
76  /* On 32-bit Windows, or no 64-bit Runtime installed. Try 32-bit registry. */
77  if (runtime == NULL) {
78  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, UNINST_KEY, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hKey) == ERROR_SUCCESS) {
79  if (RegQueryValueEx(hKey, "DisplayIcon", 0, &dwType, (BYTE*) buf, &dwBufSize) == ERROR_SUCCESS) {
80  char *slash = strrchr(buf, '\\');
81  if (slash != NULL) {
82  strcpy(slash, "\\panda3d.exe");
83  runtime = buf;
84  }
85  }
86  RegCloseKey(hKey);
87  }
88  }
89 
90  /* Backward compatibility: Runtime 1.0.4 and below looked for the below key, even though the
91  above keys should work fine, but let's just be certain.
92  Find the Panda3D applet\DefaultIcon key and extract the path to the runtime from there. */
93  if (runtime == NULL) {
94  if (RegOpenKey(HKEY_CLASSES_ROOT, "Panda3D applet\\DefaultIcon", &hKey) == ERROR_SUCCESS) {
95  if (RegQueryValueEx(hKey, 0, 0, &dwType, (BYTE*) buf, &dwBufSize) == ERROR_SUCCESS) {
96  char *slash = strrchr(buf, '\\');
97  if (slash != NULL) {
98  strcpy(slash, "\\panda3d.exe");
99  runtime = buf;
100  }
101  } else {
102  fprintf(stderr, "Failed to read registry key. Try reinstalling the Panda3D Runtime.\n");
103  return 1;
104  }
105  RegCloseKey(hKey);
106  } else {
107  fprintf(stderr, "The Panda3D Runtime does not appear to be installed!\n");
108  return 1;
109  }
110  }
111 
112  if (runtime == NULL) {
113  fprintf(stderr, "Failed to find panda3d.exe in registry. Try reinstalling the Panda3D Runtime.\n");
114  return 1;
115  }
116 
117  /* Build the command-line and run panda3d.exe. */
118  cmd = GetCommandLine();
119  newcmd = (char*) _alloca(strlen(runtime) + strlen(p3dfile) + strlen(cmd) - strlen (argv[0]) + 7);
120  sprintf(newcmd, "\"%s\" \"%s\" %s", runtime, p3dfile, cmd + strlen(argv[0]));
121  memset(&si, 0, sizeof(si));
122  si.cb = sizeof(STARTUPINFO);
123  if (CreateProcess(runtime, newcmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
124  WaitForSingleObject(pi.hProcess, INFINITE);
125  }
126  return 0;
127 }