Skip to content

Commit

Permalink
Handle both an ASCII (UTF8) and a WIDE (UTF16) version of image/vm na…
Browse files Browse the repository at this point in the history
…me/path

Note:
the Microsoft windows API mostly uses the W version (for enabling internationalized image name/path)
the image uses UTF8 encoded bytes string for communication with the VM (this is best for compatibility with Unix/Mac)
The idea here is that the implementation maintains both versions of the UTF8 and UTF16 path/name

The appropriate macro returning a TCHAR * are also provided.
This is in order to support the generic version using TCHAR, which are normally used to ease transition to UNICODE.

Note about string length:
No effort has been made so far to support long path names for image and VM.
The path is limited to MAX_PATH in UTF16.
UTF8 can eventually consume more characters than UTF16 (not necessarily more bytes).
Thus, the ASCII version has been made longer (MAX_PATH_UTF8) in order to avoid an even more restrictive limit.
  • Loading branch information
nicolas-cellier-aka-nice committed Dec 29, 2018
1 parent 1229447 commit 5f71fce
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 79 deletions.
45 changes: 35 additions & 10 deletions platforms/win32/vm/sqWin32.h
Expand Up @@ -259,21 +259,46 @@ int reverse_image_words(unsigned int *dst, unsigned int *src,int depth, int widt
/********************************************************/
/* Declarations we may need by other modules */
/********************************************************/
extern char imageName[]; /* full path and name to image */
extern TCHAR imagePath[]; /* full path to image */
extern TCHAR vmPath[]; /* full path to interpreter's directory */
extern TCHAR vmName[]; /* name of the interpreter's executable */
extern char windowTitle[]; /* window title string */
extern char vmBuildString[]; /* the vm build string */
extern TCHAR windowClassName[]; /* class name for the window */

/* Note: a character can require up to 4 bytes in UTF8 encoding
But the expansion from UTF16 -> UTF8 is never more than 3 bytes for 1 short
U+ 0000-U+ 007F - 1byte in utf8, 1 short in utf16.
U+ 0080-U+ 07FF - 2byte in utf8, 1 short in utf16.
U+ 0800-U+ FFFF - 3byte in utf8, 1 short in utf16.
U+10000-U+10FFFF - 4byte in utf8, 2 short in utf16.
*/
#define MAX_PATH_UTF8 (MAX_PATH*3)

extern char imageName []; /* full path and name to image - UTF8 */
extern WCHAR imageNameW[]; /* full path and name to image - UTF16 */
extern char imagePathA[]; /* full path to image - UTF8 */
extern WCHAR imagePathW[]; /* full path to image - UTF16 */
extern char vmPathA[]; /* full path to interpreter's directory - UTF8 */
extern WCHAR vmPathW[]; /* full path to interpreter's directory - UTF16 */
extern char vmNameA[]; /* name of the interpreter's executable - UTF8 */
extern WCHAR vmNameW[]; /* name of the interpreter's executable - UTF16 */
extern char windowTitle[]; /* window title string - UTF8 */
extern char vmBuildString[]; /* the vm build string */
extern TCHAR windowClassName[]; /* class name for the window */

#ifdef UNICODE
#define imageNameT imageNameW /* define the generic TCHAR* version */
#define imagePath imagePathW
#define vmName vmNameW
#define vmPath vmPathW
#else
#define imageNameT imageName
#define imagePath imagePathA
#define vmName vmNameA
#define vmPath vmPathA
#endif

extern UINT SQ_LAUNCH_DROP;

extern const TCHAR U_ON[];
extern const TCHAR U_OFF[];
extern const TCHAR U_GLOBAL[];
extern const TCHAR U_SLASH[];
extern const TCHAR U_BACKSLASH[];
extern const WCHAR W_BACKSLASH[];

#ifndef NO_PREFERENCES
extern HMENU vmPrefsMenu; /* preferences menu */
Expand Down Expand Up @@ -380,7 +405,7 @@ void vprintLastError(TCHAR *fmt, ...);
/******************************************************/
/* Misc functions */
/******************************************************/
DWORD SqueakImageLength(TCHAR *fileName);
DWORD SqueakImageLength(WCHAR *fileName);
int isLocalFileName(TCHAR *fileName);

#ifndef NO_PLUGIN_SUPPORT
Expand Down
31 changes: 16 additions & 15 deletions platforms/win32/vm/sqWin32Main.c
Expand Up @@ -130,7 +130,7 @@ TCHAR consoleBuffer[4096];
char stderrName[MAX_PATH+1];
char stdoutName[MAX_PATH+1];

static char vmLogDirA[MAX_PATH];
static char vmLogDirA[MAX_PATH_UTF8];
static WCHAR vmLogDirW[MAX_PATH];

TCHAR *logName = TEXT(""); /* full path and name to log file */
Expand Down Expand Up @@ -462,7 +462,7 @@ char *ioGetLogDirectory(void) {
}

sqInt ioSetLogDirectoryOfSize(void* lblIndex, sqInt sz) {
if (sz >= MAX_PATH) return 0;
if (sz >= MAX_PATH_UTF8) return 0;
strncpy(vmLogDirA, lblIndex, sz);
vmLogDirA[sz] = 0;
MultiByteToWideChar(CP_UTF8, 0, vmLogDirA, -1, vmLogDirW, MAX_PATH);
Expand Down Expand Up @@ -1405,7 +1405,7 @@ sqImageFile findEmbeddedImage(void) {
int start;
int length;

f = sqImageFileOpen(vmName, "rb");
f = sqImageFileOpen(vmNameA, "rb");
if(!f) {
MessageBox(0,"Error opening VM",VM_NAME,MB_OK);
return 0;
Expand Down Expand Up @@ -1441,6 +1441,7 @@ sqImageFile findEmbeddedImage(void) {
/* Gotcha! */
sqImageFileSeek(f, sqImageFilePosition(f) - 4);
strcpy(imageName, name);
MultiByteToWideChar(CP_UTF8,0,imageName,-1,imageNameW,MAX_PATH,NULL,NULL);
imageSize = endMarker - sqImageFilePosition(f);
return f;
}
Expand Down Expand Up @@ -1577,7 +1578,7 @@ sqMain(int argc, char *argv[])
}

SetupFilesAndPath();
ioSetLogDirectoryOfSize(vmPath, strlen(vmPath));
ioSetLogDirectoryOfSize(vmPathA, strlen(vmPathA));

/* release resources on exit */
atexit(Cleanup);
Expand Down Expand Up @@ -1620,7 +1621,7 @@ sqMain(int argc, char *argv[])


if(!imageFile) {
imageSize = SqueakImageLength(toUnicode(imageName));
imageSize = SqueakImageLength(imageNameW);
if(imageSize == 0) printUsage(2);
}

Expand Down Expand Up @@ -1650,13 +1651,13 @@ sqMain(int argc, char *argv[])

#if !NewspeakVM
/* set the CWD to the image location */
if(*imageName) {
char path[MAX_PATH+1], *ptr;
strcpy(path,imageName);
ptr = strrchr(path, '\\');
if(*imageNameW) {
WCHAR path[MAX_PATH+1], *ptr;
wcsncpy(path,imageNameW,MAX_PATH);
ptr = wcsrchr(path, '\\');
if(ptr) {
*ptr = 0;
SetCurrentDirectory(path);
*ptr = 0;
SetCurrentDirectoryW(path);
}
}
#endif /* !NewspeakVM */
Expand Down Expand Up @@ -1723,9 +1724,8 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

/* fetch us the name of the executable */
{
WCHAR vmNameW[MAX_PATH];
GetModuleFileNameW(hInst, vmNameW, MAX_PATH);
WideCharToMultiByte(CP_UTF8, 0, vmNameW, -1, vmName, MAX_PATH, NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, vmNameW, -1, vmNameA, MAX_PATH_UTF8, NULL, NULL);
}
/* parse the command line into the unix-style argc, argv, converting to
* UTF-8 on the way. */
Expand Down Expand Up @@ -2086,7 +2086,7 @@ SubsystemType()
IMAGE_OPTIONAL_HEADER image_optional_header;

/* Open the reference file. */
hImage = CreateFile(vmName,
hImage = CreateFileW(vmNameW,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
Expand Down Expand Up @@ -2150,7 +2150,8 @@ parseGenericArgs(int argc, char *argv[])

if (*imageName == 0) { /* only try to use image name if none is provided */
if (*argv[0] && IsImage(argv[0])) {
strcpy(imageName, argv[0]);
strncpy(imageName, argv[0],MAX_PATH_UTF8);
MultiByteToWideChar(CP_UTF8, 0, imageName, -1, imageNameW, MAX_PATH);
/* if provided, the image is a vm argument. */
vmOptions[numOptionsVM++] = argv[0];
}
Expand Down
12 changes: 7 additions & 5 deletions platforms/win32/vm/sqWin32Prefs.c
Expand Up @@ -194,15 +194,17 @@ void LoadPreferences()

/* get image file name from ini file */
size = GetPrivateProfileString(U_GLOBAL, TEXT("ImageFile"),
TEXT(""), imageName, MAX_PATH, squeakIniName);
TEXT(""), imageNameT, MAX_PATH, squeakIniName);
if(size > 0) {
if( !(imageName[0] == '\\' && imageName[1] == '\\') && !(imageName[1] == ':' && imageName[2] == '\\')) {
/* make the path relative to VM directory */
lstrcpy(imageName, vmName);
(lstrrchr(imageName,U_BACKSLASH[0]))[1] = 0;
size = lstrlen(imageName);
strcpy(imageName , vmNameA);
wcscpy(imageNameW, vmNameW);
(strrchr(imageName ,'\\' ))[1] = 0;
(wcsrchr(imageNameW, W_BACKSLASH[0]))[1] = 0;
size = lstrlen(imageNameT);
size = GetPrivateProfileString(U_GLOBAL, TEXT("ImageFile"),
TEXT(""), imageName + size, MAX_PATH - size, squeakIniName);
TEXT(""), imageNameT + size, MAX_PATH - size, squeakIniName);
}
}

Expand Down
19 changes: 10 additions & 9 deletions platforms/win32/vm/sqWin32Service.c
Expand Up @@ -413,12 +413,12 @@ void sqServiceInstall(void)
return;
}
/* Add the image name to the subkey. */
ok = RegSetValueEx(hk, /* subkey handle */
TEXT("Image"), /* value name */
0, /* must be zero */
REG_EXPAND_SZ, /* value type */
(LPBYTE) imageName, /* address of value data */
strlen(imageName) + 1); /* length of value data */
ok = RegSetValueExW(hk, /* subkey handle */
L"Image", /* value name */
0, /* must be zero */
REG_EXPAND_SZ, /* value type */
(LPBYTE) imageNameW, /* address of value data */
(wcslen(imageNameW)+1)*sizeof(WCHAR)); /* length of value data */
if(ok != ERROR_SUCCESS)
{
printLastError(TEXT("RegSetValueEX failed"));
Expand Down Expand Up @@ -517,14 +517,15 @@ DWORD WINAPI sqThreadMain(DWORD ignored)
TerminateThread(GetCurrentThread(), 0);
}
/* Read the image name from the subkey. */
dwSize = MAX_PATH;
ok = RegQueryValueEx(hk,TEXT("Image"),NULL, &dwType, (LPBYTE) imageName, &dwSize);
dwSize = MAX_PATH*sizeof(WCHAR);
ok = RegQueryValueExW(hk,L"Image",NULL, &dwType, (LPBYTE) imageNameW, &dwSize);
if(ok != ERROR_SUCCESS || dwType != REG_EXPAND_SZ)
{
sqStopService(TEXT("Failed to read the image name from registry"));
TerminateThread(GetCurrentThread(), 0);
}
imageName[dwSize] = 0;
imageNameW[(dwSize+1)/2] = 0;
WideCharToMultiByte(CP_UTF8, 0, imageNameW, -1, imageName, MAX_PATH_UTF8, NULL, NULL);
/* Read the log file name from the subkey. */
dwSize = MAX_PATH;
ok = RegQueryValueEx(hk,TEXT("Log"),NULL, &dwType, (LPBYTE) &tmpString, &dwSize);
Expand Down

0 comments on commit 5f71fce

Please sign in to comment.