Skip to content

Commit

Permalink
Simplify ASCII string conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
bwachter committed Jul 31, 2024
1 parent ac2142f commit fb6a63c
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 36 deletions.
61 changes: 42 additions & 19 deletions wsl-launcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,31 +82,27 @@ HANDLE startWslServiceInteractive(WslInstance *instanceData){
}

HANDLE startWslServiceInteractiveA(LPCSTR serviceName, LPCSTR distributionName, WslInstance *instanceData){
LPCSTR serviceNameA = strdup(serviceName);
LPWSTR serviceNameW;
LPWSTR serviceNameW = NULL;
LPWSTR distributionNameW = NULL;

// calculate the buffer size for the converted string
int len = MultiByteToWideChar(CP_ACP, 0, serviceNameA, -1,
NULL, 0);
int r = -1;

if (len == 0){
wslLogText(L_ERROR, L"Unable to get buffer length\n");
return NULL;
if (serviceName != NULL){
r = wslAtoW(serviceName, &serviceNameW);
if (r == -1)
return NULL;
else
instanceData->command = serviceNameW;
}

// if all worked out, allocate space, and convert the string
serviceNameW = (LPWSTR)malloc(len * sizeof(wchar_t));
len = MultiByteToWideChar(CP_ACP, 0, serviceNameA, -1,
serviceNameW, len);

if (len == 0){
wslLogText(L_ERROR, L"Unable to convert argument to unicode\n");
return NULL;
if (distributionName != NULL){
r = wslAtoW(distributionName, &distributionNameW);
if (r == -1)
return NULL;
else
instanceData->distributionName = distributionNameW;
}

instanceData->command = serviceNameW;

//HANDLE handle = startWslServiceInteractive(serviceNameW, uid);
HANDLE handle = startWslServiceInteractive(instanceData);
//free(serviceNameW);
return handle;
Expand Down Expand Up @@ -283,3 +279,30 @@ void wslRestoreUid(){
return defaultDistW;
}
*/

int wslAtoW(LPCSTR input, LPWSTR *output){
if (input == NULL)
return -1;

int len = MultiByteToWideChar(CP_ACP, 0,
input, -1,
NULL, 0);

if (len == 0){
wslLogText(L_ERROR, L"Unable to get buffer length\n");
return -1;
}

*output = (LPWSTR)malloc(len * sizeof(wchar_t));

len = MultiByteToWideChar(CP_ACP, 0,
input, -1,
*output, len);

if (len == 0){
wslLogText(L_ERROR, L"Unable to convert argument to unicode\n");
return -1;
}

return len;
}
30 changes: 22 additions & 8 deletions wsl-launcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,29 @@ struct _WslInstance{

/** Start a service inside of WSL
*
* @param serviceName the name of a service. Must be configured on Linux side
* @param uid the UID to use for the service
* @param instanceData instance configuration
* @return a handle to the process running a non-interactive WSL instance
*/
HANDLE startWslService(LPWSTR serviceName, ULONG uid);
HANDLE startWslService(WslInstance *instanceData);
/** Start an interactive service inside of WSL
*
* Typically using an interactive call in a service should be avoided, though
* it is useful for interactive tools.
*
* @param serviceName the name of a service. Must be configured on Linux side
* @param uid the UID to use for the service
* @param instanceData instance configuration
* @return a handle to the thread running an interactive WSL instance
*/
HANDLE startWslServiceInteractive(WslInstance *instanceData);
/** A convenience wrapper around startWslServiceThreadInteractive, taking an
* 8-bit string as argument, and converting it to wide.
/** A convenience wrapper around startWslServiceThreadInteractive, taking
* 8-bit strings as argument, and converting it to wide.
*
* If any of serviceName or distributionName is not NULL it'll be converted
* to a wide string, and stuffed into instanceData.
*
* @param serviceName the name of the service. May only be NULL if instanceData.command is set
* @param distributionName the name of the distribution. May always be NULL
* @return a handle to the thread running an interactive WSL instance
*
*/
HANDLE startWslServiceInteractiveA(LPCSTR serviceName, LPCSTR distributionName, WslInstance *instanceData);
/** This implements the WSL service thread (i.e., a Windows thread wrapper
Expand All @@ -70,6 +76,14 @@ void wslSetRootUid();
/** Restore a UID saved by wslSetRootUid
*/
void wslRestoreUid();

/** Convert a ASCII string to wide
*
* It's up to you to free the strings later.
*
* @param input the ASCII string to convert
* @param output a pointer to the wide string to receive the converted string
* @return -1 on error, otherwise the length of the string
*/
int wslAtoW(LPCSTR input, LPWSTR *output);

#endif
24 changes: 15 additions & 9 deletions wsl-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,10 @@ int main(int argc, char** argv){
poptContext optCon;

int optDefaultUid;
LPCWSTR optDistribution = NULL;
LPCWSTR optDistributionTar = NULL;
LPCWSTR optService = NULL;
LPCSTR optDistributionA = NULL;
LPWSTR optDistribution = NULL;
LPCSTR optDistributionTarA = NULL;
LPCSTR optServiceA = NULL;

// distribution variables
ULONG distVer, distUid;
Expand Down Expand Up @@ -146,11 +147,11 @@ int main(int argc, char** argv){
"Export the distribution. Requires -d, -t and -p" },
{ "path", 'p', 0, 0, 'p',
"The filesystem path to a distribution" },
{ "tar", 't', POPT_ARG_STRING, &optDistributionTar, 't',
{ "tar", 't', POPT_ARG_STRING, &optDistributionTarA, 't',
"The tar file for export/import" },
{ "run", 'r', POPT_ARG_STRING, &optService, 'r',
{ "run", 'r', POPT_ARG_STRING, &optServiceA, 'r',
"Run the service script" },
{ "stop", 's', POPT_ARG_STRING, &optService, 's',
{ "stop", 's', POPT_ARG_STRING, &optServiceA, 's',
"Stop the service script" },
{ "setdefault", '\0', 0, 0, 'D',
"Set the default distribution specified with -d" },
Expand All @@ -172,8 +173,14 @@ int main(int argc, char** argv){
optCon = poptGetContext(NULL, argc, (const char **)argv, optionsTable, 0);

// -d
if (optDistribution == NULL){
if (optDistributionA == NULL){
optDistribution = defaultWslDistributionName();
} else {
int r = wslAtoW(optDistributionA, &optDistribution);
if (r == -1){
wprintf(L"Error during wide character conversion, bailing out...\n");
exit(1);
}
}

// following switches just copy arguments through popt, and don't need extra
Expand Down Expand Up @@ -232,8 +239,7 @@ int main(int argc, char** argv){
case WSL_RUN:
instanceData.uid = 0;
instanceData.distributionName = optDistribution;
instanceData.command = optService;
HANDLE hThread = startWslServiceInteractive(&instanceData);
HANDLE hThread = startWslServiceInteractiveA(optServiceA, NULL, &instanceData);
while(TRUE){
DWORD result = WaitForSingleObject(hThread, INFINITE);
if (result == WAIT_OBJECT_0){
Expand Down

0 comments on commit fb6a63c

Please sign in to comment.