Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
windows: refactor uv_chdir implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
piscisaureus committed Jun 5, 2012
1 parent a0d2af0 commit 24f8a53
Showing 1 changed file with 60 additions and 25 deletions.
85 changes: 60 additions & 25 deletions src/win/util.c
Expand Up @@ -199,45 +199,80 @@ uv_err_t uv_cwd(char* buffer, size_t size) {


uv_err_t uv_chdir(const char* dir) {
uv_err_t err;
wchar_t* utf16Buffer = NULL;
size_t utf16Size;
WCHAR utf16_buffer[MAX_PATH];
size_t utf16_len;
WCHAR drive_letter, env_var[4];

if (!dir) {
err.code = UV_EINVAL;
goto done;
if (dir == NULL) {
return uv__new_artificial_error(UV_EINVAL);
}

utf16Size = uv_utf8_to_utf16(dir, NULL, 0);
if (!utf16Size) {
err = uv__new_sys_error(GetLastError());
goto done;
if (MultiByteToWideChar(CP_UTF8,
0,
dir,
-1,
utf16_buffer,
MAX_PATH) == 0) {
DWORD error = GetLastError();
/* The maximum length of the current working directory is 260 chars, */
/* including terminating null. If it doesn't fit, the path name must be */
/* too long. */
if (error == ERROR_INSUFFICIENT_BUFFER) {
return uv__new_artificial_error(UV_ENAMETOOLONG);
} else {
return uv__new_sys_error(error);
}
}

utf16Buffer = (wchar_t*)malloc(sizeof(wchar_t) * utf16Size);
if (!utf16Buffer) {
err.code = UV_ENOMEM;
goto done;
if (!SetCurrentDirectoryW(utf16_buffer)) {
return uv__new_sys_error(GetLastError());
}

if (!uv_utf8_to_utf16(dir, utf16Buffer, utf16Size)) {
err = uv__new_sys_error(GetLastError());
goto done;
/* Windows stores the drive-local path in an "hidden" environment variable, */
/* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */
/* update this, so we'll have to do it. */
utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer);
if (utf16_len == 0) {
return uv__new_sys_error(GetLastError());
} else if (utf16_len > MAX_PATH) {
return uv__new_artificial_error(UV_EIO);
}

if (_wchdir(utf16Buffer) == -1) {
err = uv__new_sys_error(_doserrno);
goto done;
/* The returned directory should not have a trailing slash, unless it */
/* points at a drive root, like c:\. Remove it if needed. */
if (utf16_buffer[utf16_len - 1] == L'\\' &&
!(utf16_len == 3 && utf16_buffer[1] == L':')) {
utf16_len--;
utf16_buffer[utf16_len] = L'\0';
}

err = uv_ok_;
if (utf16_len < 2 || utf16_buffer[1] != L':') {
/* Doesn't look like a drive letter could be there - probably an UNC */
/* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */
drive_letter = 0;
} else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') {
drive_letter = utf16_buffer[0];
} else if (utf16_buffer[0] >= L'a' && utf16_buffer[0] <= L'z') {
/* Convert to uppercase. */
drive_letter = utf16_buffer[0] - L'a' + L'A';
} else {
/* Not valid. */
drive_letter = 0;
}

done:
if (utf16Buffer) {
free(utf16Buffer);
if (drive_letter != 0) {
/* Construct the environment variable name and set it. */
env_var[0] = L'=';
env_var[1] = drive_letter;
env_var[2] = L':';
env_var[3] = L'\0';

if (!SetEnvironmentVariableW(env_var, utf16_buffer)) {
return uv__new_sys_error(GetLastError());
}
}

return err;
return uv_ok_;
}


Expand Down

0 comments on commit 24f8a53

Please sign in to comment.