mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-01 19:42:48 -05:00
Whitespace rationalisation of entire code base.
The number of people has been steadily increasing who read our source code with an editor that thinks tab stops are 4 spaces apart, as opposed to the traditional tty-derived 8 that the PuTTY code expects. So I've been wondering for ages about just fixing it, and switching to a spaces-only policy throughout the code. And I recently found out about 'git blame -w', which should make this change not too disruptive for the purposes of source-control archaeology; so perhaps now is the time. While I'm at it, I've also taken the opportunity to remove all the trailing spaces from source lines (on the basis that git dislikes them, and is the only thing that seems to have a strong opinion one way or the other). Apologies to anyone downstream of this code who has complicated patch sets to rebase past this change. I don't intend it to be needed again.
This commit is contained in:
@ -540,7 +540,7 @@ https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569(v=vs.85).aspx
|
||||
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
|
||||
|
||||
<?if $(var.DllOk) = yes ?>
|
||||
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction"
|
||||
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction"
|
||||
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
|
||||
<?endif ?>
|
||||
|
||||
|
@ -15,9 +15,9 @@
|
||||
looking controls in the client area. -->
|
||||
<assemblyIdentity type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
version="6.0.0.0"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
language="*"
|
||||
processorArchitecture="*"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
|
@ -15,9 +15,9 @@
|
||||
looking controls in the client area. -->
|
||||
<assemblyIdentity type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
version="6.0.0.0"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
language="*"
|
||||
processorArchitecture="*"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
|
@ -15,9 +15,9 @@
|
||||
looking controls in the client area. -->
|
||||
<assemblyIdentity type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
version="6.0.0.0"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
language="*"
|
||||
processorArchitecture="*"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
|
@ -15,9 +15,9 @@
|
||||
looking controls in the client area. -->
|
||||
<assemblyIdentity type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
version="6.0.0.0"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
language="*"
|
||||
processorArchitecture="*"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
|
@ -15,76 +15,76 @@ static COLORREF tip_bg;
|
||||
static COLORREF tip_text;
|
||||
|
||||
static LRESULT CALLBACK SizeTipWndProc(HWND hWnd, UINT nMsg,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
||||
switch (nMsg) {
|
||||
case WM_ERASEBKGND:
|
||||
return true;
|
||||
return true;
|
||||
|
||||
case WM_PAINT:
|
||||
{
|
||||
HBRUSH hbr;
|
||||
HGDIOBJ holdbr;
|
||||
RECT cr;
|
||||
int wtlen;
|
||||
LPTSTR wt;
|
||||
HDC hdc;
|
||||
{
|
||||
HBRUSH hbr;
|
||||
HGDIOBJ holdbr;
|
||||
RECT cr;
|
||||
int wtlen;
|
||||
LPTSTR wt;
|
||||
HDC hdc;
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
hdc = BeginPaint(hWnd, &ps);
|
||||
PAINTSTRUCT ps;
|
||||
hdc = BeginPaint(hWnd, &ps);
|
||||
|
||||
SelectObject(hdc, tip_font);
|
||||
SelectObject(hdc, GetStockObject(BLACK_PEN));
|
||||
SelectObject(hdc, tip_font);
|
||||
SelectObject(hdc, GetStockObject(BLACK_PEN));
|
||||
|
||||
hbr = CreateSolidBrush(tip_bg);
|
||||
holdbr = SelectObject(hdc, hbr);
|
||||
hbr = CreateSolidBrush(tip_bg);
|
||||
holdbr = SelectObject(hdc, hbr);
|
||||
|
||||
GetClientRect(hWnd, &cr);
|
||||
Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom);
|
||||
GetClientRect(hWnd, &cr);
|
||||
Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom);
|
||||
|
||||
wtlen = GetWindowTextLength(hWnd);
|
||||
wt = (LPTSTR) snewn(wtlen + 1, TCHAR);
|
||||
GetWindowText(hWnd, wt, wtlen + 1);
|
||||
wtlen = GetWindowTextLength(hWnd);
|
||||
wt = (LPTSTR) snewn(wtlen + 1, TCHAR);
|
||||
GetWindowText(hWnd, wt, wtlen + 1);
|
||||
|
||||
SetTextColor(hdc, tip_text);
|
||||
SetBkColor(hdc, tip_bg);
|
||||
SetTextColor(hdc, tip_text);
|
||||
SetBkColor(hdc, tip_bg);
|
||||
|
||||
TextOut(hdc, cr.left + 3, cr.top + 3, wt, wtlen);
|
||||
TextOut(hdc, cr.left + 3, cr.top + 3, wt, wtlen);
|
||||
|
||||
sfree(wt);
|
||||
sfree(wt);
|
||||
|
||||
SelectObject(hdc, holdbr);
|
||||
DeleteObject(hbr);
|
||||
SelectObject(hdc, holdbr);
|
||||
DeleteObject(hbr);
|
||||
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
return 0;
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_NCHITTEST:
|
||||
return HTTRANSPARENT;
|
||||
return HTTRANSPARENT;
|
||||
|
||||
case WM_DESTROY:
|
||||
DeleteObject(tip_font);
|
||||
tip_font = NULL;
|
||||
break;
|
||||
DeleteObject(tip_font);
|
||||
tip_font = NULL;
|
||||
break;
|
||||
|
||||
case WM_SETTEXT:
|
||||
{
|
||||
LPCTSTR str = (LPCTSTR) lParam;
|
||||
SIZE sz;
|
||||
HDC hdc = CreateCompatibleDC(NULL);
|
||||
{
|
||||
LPCTSTR str = (LPCTSTR) lParam;
|
||||
SIZE sz;
|
||||
HDC hdc = CreateCompatibleDC(NULL);
|
||||
|
||||
SelectObject(hdc, tip_font);
|
||||
GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
|
||||
SelectObject(hdc, tip_font);
|
||||
GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
|
||||
|
||||
SetWindowPos(hWnd, NULL, 0, 0, sz.cx + 6, sz.cy + 6,
|
||||
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||
InvalidateRect(hWnd, NULL, false);
|
||||
SetWindowPos(hWnd, NULL, 0, 0, sz.cx + 6, sz.cy + 6,
|
||||
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||
InvalidateRect(hWnd, NULL, false);
|
||||
|
||||
DeleteDC(hdc);
|
||||
}
|
||||
break;
|
||||
DeleteDC(hdc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, nMsg, wParam, lParam);
|
||||
@ -98,46 +98,46 @@ void UpdateSizeTip(HWND src, int cx, int cy)
|
||||
TCHAR str[32];
|
||||
|
||||
if (!tip_enabled)
|
||||
return;
|
||||
return;
|
||||
|
||||
if (!tip_wnd) {
|
||||
NONCLIENTMETRICS nci;
|
||||
NONCLIENTMETRICS nci;
|
||||
|
||||
/* First make sure the window class is registered */
|
||||
/* First make sure the window class is registered */
|
||||
|
||||
if (!tip_class) {
|
||||
WNDCLASS wc;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = SizeTipWndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hinst;
|
||||
wc.hIcon = NULL;
|
||||
wc.hCursor = NULL;
|
||||
wc.hbrBackground = NULL;
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = "SizeTipClass";
|
||||
if (!tip_class) {
|
||||
WNDCLASS wc;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = SizeTipWndProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = hinst;
|
||||
wc.hIcon = NULL;
|
||||
wc.hCursor = NULL;
|
||||
wc.hbrBackground = NULL;
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = "SizeTipClass";
|
||||
|
||||
tip_class = RegisterClass(&wc);
|
||||
}
|
||||
tip_class = RegisterClass(&wc);
|
||||
}
|
||||
#if 0
|
||||
/* Default values based on Windows Standard color scheme */
|
||||
/* Default values based on Windows Standard color scheme */
|
||||
|
||||
tip_font = GetStockObject(SYSTEM_FONT);
|
||||
tip_bg = RGB(255, 255, 225);
|
||||
tip_text = RGB(0, 0, 0);
|
||||
tip_font = GetStockObject(SYSTEM_FONT);
|
||||
tip_bg = RGB(255, 255, 225);
|
||||
tip_text = RGB(0, 0, 0);
|
||||
#endif
|
||||
|
||||
/* Prepare other GDI objects and drawing info */
|
||||
/* Prepare other GDI objects and drawing info */
|
||||
|
||||
tip_bg = GetSysColor(COLOR_INFOBK);
|
||||
tip_text = GetSysColor(COLOR_INFOTEXT);
|
||||
tip_bg = GetSysColor(COLOR_INFOBK);
|
||||
tip_text = GetSysColor(COLOR_INFOTEXT);
|
||||
|
||||
memset(&nci, 0, sizeof(NONCLIENTMETRICS));
|
||||
nci.cbSize = sizeof(NONCLIENTMETRICS);
|
||||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
|
||||
sizeof(NONCLIENTMETRICS), &nci, 0);
|
||||
tip_font = CreateFontIndirect(&nci.lfStatusFont);
|
||||
memset(&nci, 0, sizeof(NONCLIENTMETRICS));
|
||||
nci.cbSize = sizeof(NONCLIENTMETRICS);
|
||||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
|
||||
sizeof(NONCLIENTMETRICS), &nci, 0);
|
||||
tip_font = CreateFontIndirect(&nci.lfStatusFont);
|
||||
}
|
||||
|
||||
/* Generate the tip text */
|
||||
@ -145,49 +145,49 @@ void UpdateSizeTip(HWND src, int cx, int cy)
|
||||
sprintf(str, "%dx%d", cx, cy);
|
||||
|
||||
if (!tip_wnd) {
|
||||
HDC hdc;
|
||||
SIZE sz;
|
||||
RECT wr;
|
||||
int ix, iy;
|
||||
HDC hdc;
|
||||
SIZE sz;
|
||||
RECT wr;
|
||||
int ix, iy;
|
||||
|
||||
/* calculate the tip's size */
|
||||
/* calculate the tip's size */
|
||||
|
||||
hdc = CreateCompatibleDC(NULL);
|
||||
GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
|
||||
DeleteDC(hdc);
|
||||
hdc = CreateCompatibleDC(NULL);
|
||||
GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
|
||||
DeleteDC(hdc);
|
||||
|
||||
GetWindowRect(src, &wr);
|
||||
GetWindowRect(src, &wr);
|
||||
|
||||
ix = wr.left;
|
||||
if (ix < 16)
|
||||
ix = 16;
|
||||
ix = wr.left;
|
||||
if (ix < 16)
|
||||
ix = 16;
|
||||
|
||||
iy = wr.top - sz.cy;
|
||||
if (iy < 16)
|
||||
iy = 16;
|
||||
iy = wr.top - sz.cy;
|
||||
if (iy < 16)
|
||||
iy = 16;
|
||||
|
||||
/* Create the tip window */
|
||||
/* Create the tip window */
|
||||
|
||||
tip_wnd =
|
||||
CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
|
||||
MAKEINTRESOURCE(tip_class), str, WS_POPUP, ix,
|
||||
iy, sz.cx, sz.cy, NULL, NULL, hinst, NULL);
|
||||
tip_wnd =
|
||||
CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
|
||||
MAKEINTRESOURCE(tip_class), str, WS_POPUP, ix,
|
||||
iy, sz.cx, sz.cy, NULL, NULL, hinst, NULL);
|
||||
|
||||
ShowWindow(tip_wnd, SW_SHOWNOACTIVATE);
|
||||
ShowWindow(tip_wnd, SW_SHOWNOACTIVATE);
|
||||
|
||||
} else {
|
||||
|
||||
/* Tip already exists, just set the text */
|
||||
/* Tip already exists, just set the text */
|
||||
|
||||
SetWindowText(tip_wnd, str);
|
||||
SetWindowText(tip_wnd, str);
|
||||
}
|
||||
}
|
||||
|
||||
void EnableSizeTip(bool bEnable)
|
||||
{
|
||||
if (tip_wnd && !bEnable) {
|
||||
DestroyWindow(tip_wnd);
|
||||
tip_wnd = NULL;
|
||||
DestroyWindow(tip_wnd);
|
||||
tip_wnd = NULL;
|
||||
}
|
||||
|
||||
tip_enabled = bEnable;
|
||||
|
@ -11,7 +11,7 @@
|
||||
#endif
|
||||
|
||||
DECL_WINDOWS_FUNCTION(WINCAPI_GLOBAL, BOOL, CryptProtectMemory,
|
||||
(LPVOID,DWORD,DWORD));
|
||||
(LPVOID,DWORD,DWORD));
|
||||
|
||||
bool got_crypt(void);
|
||||
|
||||
|
360
windows/wincfg.c
360
windows/wincfg.c
@ -11,22 +11,22 @@
|
||||
#include "storage.h"
|
||||
|
||||
static void about_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event)
|
||||
void *data, int event)
|
||||
{
|
||||
HWND *hwndp = (HWND *)ctrl->generic.context.p;
|
||||
|
||||
if (event == EVENT_ACTION) {
|
||||
modal_about_box(*hwndp);
|
||||
modal_about_box(*hwndp);
|
||||
}
|
||||
}
|
||||
|
||||
static void help_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event)
|
||||
void *data, int event)
|
||||
{
|
||||
HWND *hwndp = (HWND *)ctrl->generic.context.p;
|
||||
|
||||
if (event == EVENT_ACTION) {
|
||||
show_help(*hwndp);
|
||||
show_help(*hwndp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,32 +34,32 @@ static void variable_pitch_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event)
|
||||
{
|
||||
if (event == EVENT_REFRESH) {
|
||||
dlg_checkbox_set(ctrl, dlg, !dlg_get_fixed_pitch_flag(dlg));
|
||||
dlg_checkbox_set(ctrl, dlg, !dlg_get_fixed_pitch_flag(dlg));
|
||||
} else if (event == EVENT_VALCHANGE) {
|
||||
dlg_set_fixed_pitch_flag(dlg, !dlg_checkbox_get(ctrl, dlg));
|
||||
dlg_set_fixed_pitch_flag(dlg, !dlg_checkbox_get(ctrl, dlg));
|
||||
}
|
||||
}
|
||||
|
||||
void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
bool midsession, int protocol)
|
||||
bool midsession, int protocol)
|
||||
{
|
||||
struct controlset *s;
|
||||
union control *c;
|
||||
char *str;
|
||||
|
||||
if (!midsession) {
|
||||
/*
|
||||
* Add the About and Help buttons to the standard panel.
|
||||
*/
|
||||
s = ctrl_getset(b, "", "", "");
|
||||
c = ctrl_pushbutton(s, "About", 'a', HELPCTX(no_help),
|
||||
about_handler, P(hwndp));
|
||||
c->generic.column = 0;
|
||||
if (has_help) {
|
||||
c = ctrl_pushbutton(s, "Help", 'h', HELPCTX(no_help),
|
||||
help_handler, P(hwndp));
|
||||
c->generic.column = 1;
|
||||
}
|
||||
/*
|
||||
* Add the About and Help buttons to the standard panel.
|
||||
*/
|
||||
s = ctrl_getset(b, "", "", "");
|
||||
c = ctrl_pushbutton(s, "About", 'a', HELPCTX(no_help),
|
||||
about_handler, P(hwndp));
|
||||
c->generic.column = 0;
|
||||
if (has_help) {
|
||||
c = ctrl_pushbutton(s, "Help", 'h', HELPCTX(no_help),
|
||||
help_handler, P(hwndp));
|
||||
c->generic.column = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -67,11 +67,11 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
* scrollbar_in_fullscreen is as well.
|
||||
*/
|
||||
s = ctrl_getset(b, "Window", "scrollback",
|
||||
"Control the scrollback in the window");
|
||||
"Control the scrollback in the window");
|
||||
ctrl_checkbox(s, "Display scrollbar in full screen mode", 'i',
|
||||
HELPCTX(window_scrollback),
|
||||
conf_checkbox_handler,
|
||||
I(CONF_scrollbar_in_fullscreen));
|
||||
HELPCTX(window_scrollback),
|
||||
conf_checkbox_handler,
|
||||
I(CONF_scrollbar_in_fullscreen));
|
||||
/*
|
||||
* Really this wants to go just after `Display scrollbar'. See
|
||||
* if we can find that control, and do some shuffling.
|
||||
@ -102,20 +102,20 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
* specific options.
|
||||
*/
|
||||
s = ctrl_getset(b, "Terminal/Keyboard", "features",
|
||||
"Enable extra keyboard features:");
|
||||
"Enable extra keyboard features:");
|
||||
ctrl_checkbox(s, "AltGr acts as Compose key", 't',
|
||||
HELPCTX(keyboard_compose),
|
||||
conf_checkbox_handler, I(CONF_compose_key));
|
||||
HELPCTX(keyboard_compose),
|
||||
conf_checkbox_handler, I(CONF_compose_key));
|
||||
ctrl_checkbox(s, "Control-Alt is different from AltGr", 'd',
|
||||
HELPCTX(keyboard_ctrlalt),
|
||||
conf_checkbox_handler, I(CONF_ctrlaltkeys));
|
||||
HELPCTX(keyboard_ctrlalt),
|
||||
conf_checkbox_handler, I(CONF_ctrlaltkeys));
|
||||
|
||||
/*
|
||||
* Windows allows an arbitrary .WAV to be played as a bell, and
|
||||
* also the use of the PC speaker. For this we must search the
|
||||
* existing controlset for the radio-button set controlling the
|
||||
* `beep' option, and add extra buttons to it.
|
||||
*
|
||||
*
|
||||
* Note that although this _looks_ like a hideous hack, it's
|
||||
* actually all above board. The well-defined interface to the
|
||||
* per-platform dialog box code is the _data structures_ `union
|
||||
@ -129,74 +129,74 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
*/
|
||||
s = ctrl_getset(b, "Terminal/Bell", "style", "Set the style of bell");
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_RADIO &&
|
||||
c->generic.context.i == CONF_beep) {
|
||||
assert(c->generic.handler == conf_radiobutton_handler);
|
||||
c->radio.nbuttons += 2;
|
||||
c->radio.buttons =
|
||||
sresize(c->radio.buttons, c->radio.nbuttons, char *);
|
||||
c->radio.buttons[c->radio.nbuttons-1] =
|
||||
dupstr("Play a custom sound file");
|
||||
c->radio.buttons[c->radio.nbuttons-2] =
|
||||
dupstr("Beep using the PC speaker");
|
||||
c->radio.buttondata =
|
||||
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
|
||||
c->radio.buttondata[c->radio.nbuttons-1] = I(BELL_WAVEFILE);
|
||||
c->radio.buttondata[c->radio.nbuttons-2] = I(BELL_PCSPEAKER);
|
||||
if (c->radio.shortcuts) {
|
||||
c->radio.shortcuts =
|
||||
sresize(c->radio.shortcuts, c->radio.nbuttons, char);
|
||||
c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT;
|
||||
c->radio.shortcuts[c->radio.nbuttons-2] = NO_SHORTCUT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_RADIO &&
|
||||
c->generic.context.i == CONF_beep) {
|
||||
assert(c->generic.handler == conf_radiobutton_handler);
|
||||
c->radio.nbuttons += 2;
|
||||
c->radio.buttons =
|
||||
sresize(c->radio.buttons, c->radio.nbuttons, char *);
|
||||
c->radio.buttons[c->radio.nbuttons-1] =
|
||||
dupstr("Play a custom sound file");
|
||||
c->radio.buttons[c->radio.nbuttons-2] =
|
||||
dupstr("Beep using the PC speaker");
|
||||
c->radio.buttondata =
|
||||
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
|
||||
c->radio.buttondata[c->radio.nbuttons-1] = I(BELL_WAVEFILE);
|
||||
c->radio.buttondata[c->radio.nbuttons-2] = I(BELL_PCSPEAKER);
|
||||
if (c->radio.shortcuts) {
|
||||
c->radio.shortcuts =
|
||||
sresize(c->radio.shortcuts, c->radio.nbuttons, char);
|
||||
c->radio.shortcuts[c->radio.nbuttons-1] = NO_SHORTCUT;
|
||||
c->radio.shortcuts[c->radio.nbuttons-2] = NO_SHORTCUT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctrl_filesel(s, "Custom sound file to play as a bell:", NO_SHORTCUT,
|
||||
FILTER_WAVE_FILES, false, "Select bell sound file",
|
||||
HELPCTX(bell_style),
|
||||
conf_filesel_handler, I(CONF_bell_wavefile));
|
||||
FILTER_WAVE_FILES, false, "Select bell sound file",
|
||||
HELPCTX(bell_style),
|
||||
conf_filesel_handler, I(CONF_bell_wavefile));
|
||||
|
||||
/*
|
||||
* While we've got this box open, taskbar flashing on a bell is
|
||||
* also Windows-specific.
|
||||
*/
|
||||
ctrl_radiobuttons(s, "Taskbar/caption indication on bell:", 'i', 3,
|
||||
HELPCTX(bell_taskbar),
|
||||
conf_radiobutton_handler,
|
||||
I(CONF_beep_ind),
|
||||
"Disabled", I(B_IND_DISABLED),
|
||||
"Flashing", I(B_IND_FLASH),
|
||||
"Steady", I(B_IND_STEADY), NULL);
|
||||
HELPCTX(bell_taskbar),
|
||||
conf_radiobutton_handler,
|
||||
I(CONF_beep_ind),
|
||||
"Disabled", I(B_IND_DISABLED),
|
||||
"Flashing", I(B_IND_FLASH),
|
||||
"Steady", I(B_IND_STEADY), NULL);
|
||||
|
||||
/*
|
||||
* The sunken-edge border is a Windows GUI feature.
|
||||
*/
|
||||
s = ctrl_getset(b, "Window/Appearance", "border",
|
||||
"Adjust the window border");
|
||||
"Adjust the window border");
|
||||
ctrl_checkbox(s, "Sunken-edge border (slightly thicker)", 's',
|
||||
HELPCTX(appearance_border),
|
||||
conf_checkbox_handler, I(CONF_sunken_edge));
|
||||
HELPCTX(appearance_border),
|
||||
conf_checkbox_handler, I(CONF_sunken_edge));
|
||||
|
||||
/*
|
||||
* Configurable font quality settings for Windows.
|
||||
*/
|
||||
s = ctrl_getset(b, "Window/Appearance", "font",
|
||||
"Font settings");
|
||||
"Font settings");
|
||||
ctrl_checkbox(s, "Allow selection of variable-pitch fonts", NO_SHORTCUT,
|
||||
HELPCTX(appearance_font), variable_pitch_handler, I(0));
|
||||
ctrl_radiobuttons(s, "Font quality:", 'q', 2,
|
||||
HELPCTX(appearance_font),
|
||||
conf_radiobutton_handler,
|
||||
I(CONF_font_quality),
|
||||
"Antialiased", I(FQ_ANTIALIASED),
|
||||
"Non-Antialiased", I(FQ_NONANTIALIASED),
|
||||
"ClearType", I(FQ_CLEARTYPE),
|
||||
"Default", I(FQ_DEFAULT), NULL);
|
||||
HELPCTX(appearance_font),
|
||||
conf_radiobutton_handler,
|
||||
I(CONF_font_quality),
|
||||
"Antialiased", I(FQ_ANTIALIASED),
|
||||
"Non-Antialiased", I(FQ_NONANTIALIASED),
|
||||
"ClearType", I(FQ_CLEARTYPE),
|
||||
"Default", I(FQ_DEFAULT), NULL);
|
||||
|
||||
/*
|
||||
* Cyrillic Lock is a horrid misfeature even on Windows, and
|
||||
@ -205,19 +205,19 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
*/
|
||||
s = ctrl_getset(b, "Window/Translation", "tweaks", NULL);
|
||||
ctrl_checkbox(s, "Caps Lock acts as Cyrillic switch", 's',
|
||||
HELPCTX(translation_cyrillic),
|
||||
conf_checkbox_handler,
|
||||
I(CONF_xlat_capslockcyr));
|
||||
HELPCTX(translation_cyrillic),
|
||||
conf_checkbox_handler,
|
||||
I(CONF_xlat_capslockcyr));
|
||||
|
||||
/*
|
||||
* On Windows we can use but not enumerate translation tables
|
||||
* from the operating system. Briefly document this.
|
||||
*/
|
||||
s = ctrl_getset(b, "Window/Translation", "trans",
|
||||
"Character set translation on received data");
|
||||
"Character set translation on received data");
|
||||
ctrl_text(s, "(Codepages supported by Windows but not listed here, "
|
||||
"such as CP866 on many systems, can be entered manually)",
|
||||
HELPCTX(translation_codepage));
|
||||
"such as CP866 on many systems, can be entered manually)",
|
||||
HELPCTX(translation_codepage));
|
||||
|
||||
/*
|
||||
* Windows has the weird OEM font mode, which gives us some
|
||||
@ -228,51 +228,51 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
s = ctrl_getset(b, "Window/Translation", "linedraw", str);
|
||||
sfree(str);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_RADIO &&
|
||||
c->generic.context.i == CONF_vtmode) {
|
||||
assert(c->generic.handler == conf_radiobutton_handler);
|
||||
c->radio.nbuttons += 3;
|
||||
c->radio.buttons =
|
||||
sresize(c->radio.buttons, c->radio.nbuttons, char *);
|
||||
c->radio.buttons[c->radio.nbuttons-3] =
|
||||
dupstr("Font has XWindows encoding");
|
||||
c->radio.buttons[c->radio.nbuttons-2] =
|
||||
dupstr("Use font in both ANSI and OEM modes");
|
||||
c->radio.buttons[c->radio.nbuttons-1] =
|
||||
dupstr("Use font in OEM mode only");
|
||||
c->radio.buttondata =
|
||||
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
|
||||
c->radio.buttondata[c->radio.nbuttons-3] = I(VT_XWINDOWS);
|
||||
c->radio.buttondata[c->radio.nbuttons-2] = I(VT_OEMANSI);
|
||||
c->radio.buttondata[c->radio.nbuttons-1] = I(VT_OEMONLY);
|
||||
if (!c->radio.shortcuts) {
|
||||
int j;
|
||||
c->radio.shortcuts = snewn(c->radio.nbuttons, char);
|
||||
for (j = 0; j < c->radio.nbuttons; j++)
|
||||
c->radio.shortcuts[j] = NO_SHORTCUT;
|
||||
} else {
|
||||
c->radio.shortcuts = sresize(c->radio.shortcuts,
|
||||
c->radio.nbuttons, char);
|
||||
}
|
||||
c->radio.shortcuts[c->radio.nbuttons-3] = 'x';
|
||||
c->radio.shortcuts[c->radio.nbuttons-2] = 'b';
|
||||
c->radio.shortcuts[c->radio.nbuttons-1] = 'e';
|
||||
break;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_RADIO &&
|
||||
c->generic.context.i == CONF_vtmode) {
|
||||
assert(c->generic.handler == conf_radiobutton_handler);
|
||||
c->radio.nbuttons += 3;
|
||||
c->radio.buttons =
|
||||
sresize(c->radio.buttons, c->radio.nbuttons, char *);
|
||||
c->radio.buttons[c->radio.nbuttons-3] =
|
||||
dupstr("Font has XWindows encoding");
|
||||
c->radio.buttons[c->radio.nbuttons-2] =
|
||||
dupstr("Use font in both ANSI and OEM modes");
|
||||
c->radio.buttons[c->radio.nbuttons-1] =
|
||||
dupstr("Use font in OEM mode only");
|
||||
c->radio.buttondata =
|
||||
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
|
||||
c->radio.buttondata[c->radio.nbuttons-3] = I(VT_XWINDOWS);
|
||||
c->radio.buttondata[c->radio.nbuttons-2] = I(VT_OEMANSI);
|
||||
c->radio.buttondata[c->radio.nbuttons-1] = I(VT_OEMONLY);
|
||||
if (!c->radio.shortcuts) {
|
||||
int j;
|
||||
c->radio.shortcuts = snewn(c->radio.nbuttons, char);
|
||||
for (j = 0; j < c->radio.nbuttons; j++)
|
||||
c->radio.shortcuts[j] = NO_SHORTCUT;
|
||||
} else {
|
||||
c->radio.shortcuts = sresize(c->radio.shortcuts,
|
||||
c->radio.nbuttons, char);
|
||||
}
|
||||
c->radio.shortcuts[c->radio.nbuttons-3] = 'x';
|
||||
c->radio.shortcuts[c->radio.nbuttons-2] = 'b';
|
||||
c->radio.shortcuts[c->radio.nbuttons-1] = 'e';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RTF paste is Windows-specific.
|
||||
*/
|
||||
s = ctrl_getset(b, "Window/Selection/Copy", "format",
|
||||
"Formatting of copied characters");
|
||||
"Formatting of copied characters");
|
||||
ctrl_checkbox(s, "Copy to clipboard in RTF as well as plain text", 'f',
|
||||
HELPCTX(copy_rtf),
|
||||
conf_checkbox_handler, I(CONF_rtf_paste));
|
||||
HELPCTX(copy_rtf),
|
||||
conf_checkbox_handler, I(CONF_rtf_paste));
|
||||
|
||||
/*
|
||||
* Windows often has no middle button, so we supply a selection
|
||||
@ -280,14 +280,14 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
* the right button instead.
|
||||
*/
|
||||
s = ctrl_getset(b, "Window/Selection", "mouse",
|
||||
"Control use of mouse");
|
||||
"Control use of mouse");
|
||||
ctrl_radiobuttons(s, "Action of mouse buttons:", 'm', 1,
|
||||
HELPCTX(selection_buttons),
|
||||
conf_radiobutton_handler,
|
||||
I(CONF_mouse_is_xterm),
|
||||
"Windows (Middle extends, Right brings up menu)", I(2),
|
||||
"Compromise (Middle extends, Right pastes)", I(0),
|
||||
"xterm (Right extends, Middle pastes)", I(1), NULL);
|
||||
HELPCTX(selection_buttons),
|
||||
conf_radiobutton_handler,
|
||||
I(CONF_mouse_is_xterm),
|
||||
"Windows (Middle extends, Right brings up menu)", I(2),
|
||||
"Compromise (Middle extends, Right pastes)", I(0),
|
||||
"xterm (Right extends, Middle pastes)", I(1), NULL);
|
||||
/*
|
||||
* This really ought to go at the _top_ of its box, not the
|
||||
* bottom, so we'll just do some shuffling now we've set it
|
||||
@ -301,10 +301,10 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
* Logical palettes don't even make sense anywhere except Windows.
|
||||
*/
|
||||
s = ctrl_getset(b, "Window/Colours", "general",
|
||||
"General options for colour usage");
|
||||
"General options for colour usage");
|
||||
ctrl_checkbox(s, "Attempt to use logical palettes", 'l',
|
||||
HELPCTX(colours_logpal),
|
||||
conf_checkbox_handler, I(CONF_try_palette));
|
||||
HELPCTX(colours_logpal),
|
||||
conf_checkbox_handler, I(CONF_try_palette));
|
||||
ctrl_checkbox(s, "Use system colours", 's',
|
||||
HELPCTX(colours_system),
|
||||
conf_checkbox_handler, I(CONF_system_colour));
|
||||
@ -315,13 +315,13 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
*/
|
||||
s = ctrl_getset(b, "Window", "size", "Set the size of the window");
|
||||
ctrl_radiobuttons(s, "When window is resized:", 'z', 1,
|
||||
HELPCTX(window_resize),
|
||||
conf_radiobutton_handler,
|
||||
I(CONF_resize_action),
|
||||
"Change the number of rows and columns", I(RESIZE_TERM),
|
||||
"Change the size of the font", I(RESIZE_FONT),
|
||||
"Change font size only when maximised", I(RESIZE_EITHER),
|
||||
"Forbid resizing completely", I(RESIZE_DISABLED), NULL);
|
||||
HELPCTX(window_resize),
|
||||
conf_radiobutton_handler,
|
||||
I(CONF_resize_action),
|
||||
"Change the number of rows and columns", I(RESIZE_TERM),
|
||||
"Change the size of the font", I(RESIZE_FONT),
|
||||
"Change font size only when maximised", I(RESIZE_EITHER),
|
||||
"Forbid resizing completely", I(RESIZE_DISABLED), NULL);
|
||||
|
||||
/*
|
||||
* Most of the Window/Behaviour stuff is there to mimic Windows
|
||||
@ -330,57 +330,57 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
*/
|
||||
s = ctrl_getset(b, "Window/Behaviour", "main", NULL);
|
||||
ctrl_checkbox(s, "Window closes on ALT-F4", '4',
|
||||
HELPCTX(behaviour_altf4),
|
||||
conf_checkbox_handler, I(CONF_alt_f4));
|
||||
HELPCTX(behaviour_altf4),
|
||||
conf_checkbox_handler, I(CONF_alt_f4));
|
||||
ctrl_checkbox(s, "System menu appears on ALT-Space", 'y',
|
||||
HELPCTX(behaviour_altspace),
|
||||
conf_checkbox_handler, I(CONF_alt_space));
|
||||
HELPCTX(behaviour_altspace),
|
||||
conf_checkbox_handler, I(CONF_alt_space));
|
||||
ctrl_checkbox(s, "System menu appears on ALT alone", 'l',
|
||||
HELPCTX(behaviour_altonly),
|
||||
conf_checkbox_handler, I(CONF_alt_only));
|
||||
HELPCTX(behaviour_altonly),
|
||||
conf_checkbox_handler, I(CONF_alt_only));
|
||||
ctrl_checkbox(s, "Ensure window is always on top", 'e',
|
||||
HELPCTX(behaviour_alwaysontop),
|
||||
conf_checkbox_handler, I(CONF_alwaysontop));
|
||||
HELPCTX(behaviour_alwaysontop),
|
||||
conf_checkbox_handler, I(CONF_alwaysontop));
|
||||
ctrl_checkbox(s, "Full screen on Alt-Enter", 'f',
|
||||
HELPCTX(behaviour_altenter),
|
||||
conf_checkbox_handler,
|
||||
I(CONF_fullscreenonaltenter));
|
||||
HELPCTX(behaviour_altenter),
|
||||
conf_checkbox_handler,
|
||||
I(CONF_fullscreenonaltenter));
|
||||
|
||||
/*
|
||||
* Windows supports a local-command proxy. This also means we
|
||||
* must adjust the text on the `Telnet command' control.
|
||||
*/
|
||||
if (!midsession) {
|
||||
int i;
|
||||
int i;
|
||||
s = ctrl_getset(b, "Connection/Proxy", "basics", NULL);
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_RADIO &&
|
||||
c->generic.context.i == CONF_proxy_type) {
|
||||
assert(c->generic.handler == conf_radiobutton_handler);
|
||||
c->radio.nbuttons++;
|
||||
c->radio.buttons =
|
||||
sresize(c->radio.buttons, c->radio.nbuttons, char *);
|
||||
c->radio.buttons[c->radio.nbuttons-1] =
|
||||
dupstr("Local");
|
||||
c->radio.buttondata =
|
||||
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
|
||||
c->radio.buttondata[c->radio.nbuttons-1] = I(PROXY_CMD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_RADIO &&
|
||||
c->generic.context.i == CONF_proxy_type) {
|
||||
assert(c->generic.handler == conf_radiobutton_handler);
|
||||
c->radio.nbuttons++;
|
||||
c->radio.buttons =
|
||||
sresize(c->radio.buttons, c->radio.nbuttons, char *);
|
||||
c->radio.buttons[c->radio.nbuttons-1] =
|
||||
dupstr("Local");
|
||||
c->radio.buttondata =
|
||||
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
|
||||
c->radio.buttondata[c->radio.nbuttons-1] = I(PROXY_CMD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_EDITBOX &&
|
||||
c->generic.context.i == CONF_proxy_telnet_command) {
|
||||
assert(c->generic.handler == conf_editbox_handler);
|
||||
sfree(c->generic.label);
|
||||
c->generic.label = dupstr("Telnet command, or local"
|
||||
" proxy command");
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_EDITBOX &&
|
||||
c->generic.context.i == CONF_proxy_telnet_command) {
|
||||
assert(c->generic.handler == conf_editbox_handler);
|
||||
sfree(c->generic.label);
|
||||
c->generic.label = dupstr("Telnet command, or local"
|
||||
" proxy command");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -394,10 +394,10 @@ void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
* means to override it.
|
||||
*/
|
||||
if (!midsession && backend_vt_from_proto(PROT_SSH)) {
|
||||
s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding");
|
||||
ctrl_filesel(s, "X authority file for local display", 't',
|
||||
NULL, false, "Select X authority file",
|
||||
HELPCTX(ssh_tunnels_xauthority),
|
||||
conf_filesel_handler, I(CONF_xauthfile));
|
||||
s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding");
|
||||
ctrl_filesel(s, "X authority file for local display", 't',
|
||||
NULL, false, "Select X authority file",
|
||||
HELPCTX(ssh_tunnels_xauthority),
|
||||
conf_filesel_handler, I(CONF_xauthfile));
|
||||
}
|
||||
}
|
||||
|
@ -93,53 +93,53 @@ int console_verify_ssh_host_key(
|
||||
DWORD savemode, i;
|
||||
|
||||
static const char absentmsg_batch[] =
|
||||
"The server's host key is not cached in the registry. You\n"
|
||||
"have no guarantee that the server is the computer you\n"
|
||||
"think it is.\n"
|
||||
"The server's %s key fingerprint is:\n"
|
||||
"%s\n"
|
||||
"Connection abandoned.\n";
|
||||
"The server's host key is not cached in the registry. You\n"
|
||||
"have no guarantee that the server is the computer you\n"
|
||||
"think it is.\n"
|
||||
"The server's %s key fingerprint is:\n"
|
||||
"%s\n"
|
||||
"Connection abandoned.\n";
|
||||
static const char absentmsg[] =
|
||||
"The server's host key is not cached in the registry. You\n"
|
||||
"have no guarantee that the server is the computer you\n"
|
||||
"think it is.\n"
|
||||
"The server's %s key fingerprint is:\n"
|
||||
"%s\n"
|
||||
"If you trust this host, enter \"y\" to add the key to\n"
|
||||
"PuTTY's cache and carry on connecting.\n"
|
||||
"If you want to carry on connecting just once, without\n"
|
||||
"adding the key to the cache, enter \"n\".\n"
|
||||
"If you do not trust this host, press Return to abandon the\n"
|
||||
"connection.\n"
|
||||
"Store key in cache? (y/n) ";
|
||||
"The server's host key is not cached in the registry. You\n"
|
||||
"have no guarantee that the server is the computer you\n"
|
||||
"think it is.\n"
|
||||
"The server's %s key fingerprint is:\n"
|
||||
"%s\n"
|
||||
"If you trust this host, enter \"y\" to add the key to\n"
|
||||
"PuTTY's cache and carry on connecting.\n"
|
||||
"If you want to carry on connecting just once, without\n"
|
||||
"adding the key to the cache, enter \"n\".\n"
|
||||
"If you do not trust this host, press Return to abandon the\n"
|
||||
"connection.\n"
|
||||
"Store key in cache? (y/n) ";
|
||||
|
||||
static const char wrongmsg_batch[] =
|
||||
"WARNING - POTENTIAL SECURITY BREACH!\n"
|
||||
"The server's host key does not match the one PuTTY has\n"
|
||||
"cached in the registry. This means that either the\n"
|
||||
"server administrator has changed the host key, or you\n"
|
||||
"have actually connected to another computer pretending\n"
|
||||
"to be the server.\n"
|
||||
"The new %s key fingerprint is:\n"
|
||||
"%s\n"
|
||||
"Connection abandoned.\n";
|
||||
"WARNING - POTENTIAL SECURITY BREACH!\n"
|
||||
"The server's host key does not match the one PuTTY has\n"
|
||||
"cached in the registry. This means that either the\n"
|
||||
"server administrator has changed the host key, or you\n"
|
||||
"have actually connected to another computer pretending\n"
|
||||
"to be the server.\n"
|
||||
"The new %s key fingerprint is:\n"
|
||||
"%s\n"
|
||||
"Connection abandoned.\n";
|
||||
static const char wrongmsg[] =
|
||||
"WARNING - POTENTIAL SECURITY BREACH!\n"
|
||||
"The server's host key does not match the one PuTTY has\n"
|
||||
"cached in the registry. This means that either the\n"
|
||||
"server administrator has changed the host key, or you\n"
|
||||
"have actually connected to another computer pretending\n"
|
||||
"to be the server.\n"
|
||||
"The new %s key fingerprint is:\n"
|
||||
"%s\n"
|
||||
"If you were expecting this change and trust the new key,\n"
|
||||
"enter \"y\" to update PuTTY's cache and continue connecting.\n"
|
||||
"If you want to carry on connecting but without updating\n"
|
||||
"the cache, enter \"n\".\n"
|
||||
"If you want to abandon the connection completely, press\n"
|
||||
"Return to cancel. Pressing Return is the ONLY guaranteed\n"
|
||||
"safe choice.\n"
|
||||
"Update cached key? (y/n, Return cancels connection) ";
|
||||
"WARNING - POTENTIAL SECURITY BREACH!\n"
|
||||
"The server's host key does not match the one PuTTY has\n"
|
||||
"cached in the registry. This means that either the\n"
|
||||
"server administrator has changed the host key, or you\n"
|
||||
"have actually connected to another computer pretending\n"
|
||||
"to be the server.\n"
|
||||
"The new %s key fingerprint is:\n"
|
||||
"%s\n"
|
||||
"If you were expecting this change and trust the new key,\n"
|
||||
"enter \"y\" to update PuTTY's cache and continue connecting.\n"
|
||||
"If you want to carry on connecting but without updating\n"
|
||||
"the cache, enter \"n\".\n"
|
||||
"If you want to abandon the connection completely, press\n"
|
||||
"Return to cancel. Pressing Return is the ONLY guaranteed\n"
|
||||
"safe choice.\n"
|
||||
"Update cached key? (y/n, Return cancels connection) ";
|
||||
|
||||
static const char abandoned[] = "Connection abandoned.\n";
|
||||
|
||||
@ -150,24 +150,24 @@ int console_verify_ssh_host_key(
|
||||
*/
|
||||
ret = verify_host_key(host, port, keytype, keystr);
|
||||
|
||||
if (ret == 0) /* success - key matched OK */
|
||||
return 1;
|
||||
if (ret == 0) /* success - key matched OK */
|
||||
return 1;
|
||||
|
||||
if (ret == 2) { /* key was different */
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, wrongmsg_batch, keytype, fingerprint);
|
||||
if (ret == 2) { /* key was different */
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, wrongmsg_batch, keytype, fingerprint);
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, wrongmsg, keytype, fingerprint);
|
||||
fflush(stderr);
|
||||
}
|
||||
fprintf(stderr, wrongmsg, keytype, fingerprint);
|
||||
fflush(stderr);
|
||||
}
|
||||
if (ret == 1) { /* key was absent */
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, absentmsg_batch, keytype, fingerprint);
|
||||
if (ret == 1) { /* key was absent */
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, absentmsg_batch, keytype, fingerprint);
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, absentmsg, keytype, fingerprint);
|
||||
fflush(stderr);
|
||||
}
|
||||
fprintf(stderr, absentmsg, keytype, fingerprint);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
line[0] = '\0'; /* fail safe if ReadFile returns no data */
|
||||
@ -175,16 +175,16 @@ int console_verify_ssh_host_key(
|
||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
GetConsoleMode(hin, &savemode);
|
||||
SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
ReadFile(hin, line, sizeof(line) - 1, &i, NULL);
|
||||
SetConsoleMode(hin, savemode);
|
||||
|
||||
if (line[0] != '\0' && line[0] != '\r' && line[0] != '\n') {
|
||||
if (line[0] == 'y' || line[0] == 'Y')
|
||||
store_host_key(host, port, keytype, keystr);
|
||||
if (line[0] == 'y' || line[0] == 'Y')
|
||||
store_host_key(host, port, keytype, keystr);
|
||||
return 1;
|
||||
} else {
|
||||
fprintf(stderr, abandoned);
|
||||
fprintf(stderr, abandoned);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -197,20 +197,20 @@ int console_confirm_weak_crypto_primitive(
|
||||
DWORD savemode, i;
|
||||
|
||||
static const char msg[] =
|
||||
"The first %s supported by the server is\n"
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Continue with connection? (y/n) ";
|
||||
"The first %s supported by the server is\n"
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Continue with connection? (y/n) ";
|
||||
static const char msg_batch[] =
|
||||
"The first %s supported by the server is\n"
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Connection abandoned.\n";
|
||||
"The first %s supported by the server is\n"
|
||||
"%s, which is below the configured warning threshold.\n"
|
||||
"Connection abandoned.\n";
|
||||
static const char abandoned[] = "Connection abandoned.\n";
|
||||
|
||||
char line[32];
|
||||
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, msg_batch, algtype, algname);
|
||||
return 0;
|
||||
fprintf(stderr, msg_batch, algtype, algname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, msg, algtype, algname);
|
||||
@ -219,15 +219,15 @@ int console_confirm_weak_crypto_primitive(
|
||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
GetConsoleMode(hin, &savemode);
|
||||
SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
ReadFile(hin, line, sizeof(line) - 1, &i, NULL);
|
||||
SetConsoleMode(hin, savemode);
|
||||
|
||||
if (line[0] == 'y' || line[0] == 'Y') {
|
||||
return 1;
|
||||
return 1;
|
||||
} else {
|
||||
fprintf(stderr, abandoned);
|
||||
return 0;
|
||||
fprintf(stderr, abandoned);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,26 +239,26 @@ int console_confirm_weak_cached_hostkey(
|
||||
DWORD savemode, i;
|
||||
|
||||
static const char msg[] =
|
||||
"The first host key type we have stored for this server\n"
|
||||
"is %s, which is below the configured warning threshold.\n"
|
||||
"The server also provides the following types of host key\n"
|
||||
"The first host key type we have stored for this server\n"
|
||||
"is %s, which is below the configured warning threshold.\n"
|
||||
"The server also provides the following types of host key\n"
|
||||
"above the threshold, which we do not have stored:\n"
|
||||
"%s\n"
|
||||
"Continue with connection? (y/n) ";
|
||||
"Continue with connection? (y/n) ";
|
||||
static const char msg_batch[] =
|
||||
"The first host key type we have stored for this server\n"
|
||||
"is %s, which is below the configured warning threshold.\n"
|
||||
"The server also provides the following types of host key\n"
|
||||
"The first host key type we have stored for this server\n"
|
||||
"is %s, which is below the configured warning threshold.\n"
|
||||
"The server also provides the following types of host key\n"
|
||||
"above the threshold, which we do not have stored:\n"
|
||||
"%s\n"
|
||||
"Connection abandoned.\n";
|
||||
"Connection abandoned.\n";
|
||||
static const char abandoned[] = "Connection abandoned.\n";
|
||||
|
||||
char line[32];
|
||||
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, msg_batch, algname, betteralgs);
|
||||
return 0;
|
||||
fprintf(stderr, msg_batch, algname, betteralgs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, msg, algname, betteralgs);
|
||||
@ -267,15 +267,15 @@ int console_confirm_weak_cached_hostkey(
|
||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
GetConsoleMode(hin, &savemode);
|
||||
SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
ReadFile(hin, line, sizeof(line) - 1, &i, NULL);
|
||||
SetConsoleMode(hin, savemode);
|
||||
|
||||
if (line[0] == 'y' || line[0] == 'Y') {
|
||||
return 1;
|
||||
return 1;
|
||||
} else {
|
||||
fprintf(stderr, abandoned);
|
||||
return 0;
|
||||
fprintf(stderr, abandoned);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,24 +319,24 @@ static int console_askappend(LogPolicy *lp, Filename *filename,
|
||||
DWORD savemode, i;
|
||||
|
||||
static const char msgtemplate[] =
|
||||
"The session log file \"%.*s\" already exists.\n"
|
||||
"You can overwrite it with a new session log,\n"
|
||||
"append your session log to the end of it,\n"
|
||||
"or disable session logging for this session.\n"
|
||||
"Enter \"y\" to wipe the file, \"n\" to append to it,\n"
|
||||
"or just press Return to disable logging.\n"
|
||||
"Wipe the log file? (y/n, Return cancels logging) ";
|
||||
"The session log file \"%.*s\" already exists.\n"
|
||||
"You can overwrite it with a new session log,\n"
|
||||
"append your session log to the end of it,\n"
|
||||
"or disable session logging for this session.\n"
|
||||
"Enter \"y\" to wipe the file, \"n\" to append to it,\n"
|
||||
"or just press Return to disable logging.\n"
|
||||
"Wipe the log file? (y/n, Return cancels logging) ";
|
||||
|
||||
static const char msgtemplate_batch[] =
|
||||
"The session log file \"%.*s\" already exists.\n"
|
||||
"Logging will not be enabled.\n";
|
||||
"The session log file \"%.*s\" already exists.\n"
|
||||
"Logging will not be enabled.\n";
|
||||
|
||||
char line[32];
|
||||
|
||||
if (console_batch_mode) {
|
||||
fprintf(stderr, msgtemplate_batch, FILENAME_MAX, filename->path);
|
||||
fflush(stderr);
|
||||
return 0;
|
||||
fprintf(stderr, msgtemplate_batch, FILENAME_MAX, filename->path);
|
||||
fflush(stderr);
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, msgtemplate, FILENAME_MAX, filename->path);
|
||||
fflush(stderr);
|
||||
@ -344,21 +344,21 @@ static int console_askappend(LogPolicy *lp, Filename *filename,
|
||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
GetConsoleMode(hin, &savemode);
|
||||
SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
|
||||
ReadFile(hin, line, sizeof(line) - 1, &i, NULL);
|
||||
SetConsoleMode(hin, savemode);
|
||||
|
||||
if (line[0] == 'y' || line[0] == 'Y')
|
||||
return 2;
|
||||
return 2;
|
||||
else if (line[0] == 'n' || line[0] == 'N')
|
||||
return 1;
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Warn about the obsolescent key file format.
|
||||
*
|
||||
*
|
||||
* Uniquely among these functions, this one does _not_ expect a
|
||||
* frontend handle. This means that if PuTTY is ported to a
|
||||
* platform which requires frontend handles, this function will be
|
||||
@ -369,15 +369,15 @@ static int console_askappend(LogPolicy *lp, Filename *filename,
|
||||
void old_keyfile_warning(void)
|
||||
{
|
||||
static const char message[] =
|
||||
"You are loading an SSH-2 private key which has an\n"
|
||||
"old version of the file format. This means your key\n"
|
||||
"file is not fully tamperproof. Future versions of\n"
|
||||
"PuTTY may stop supporting this private key format,\n"
|
||||
"so we recommend you convert your key to the new\n"
|
||||
"format.\n"
|
||||
"\n"
|
||||
"Once the key is loaded into PuTTYgen, you can perform\n"
|
||||
"this conversion simply by saving it again.\n";
|
||||
"You are loading an SSH-2 private key which has an\n"
|
||||
"old version of the file format. This means your key\n"
|
||||
"file is not fully tamperproof. Future versions of\n"
|
||||
"PuTTY may stop supporting this private key format,\n"
|
||||
"so we recommend you convert your key to the new\n"
|
||||
"format.\n"
|
||||
"\n"
|
||||
"Once the key is loaded into PuTTYgen, you can perform\n"
|
||||
"this conversion simply by saving it again.\n";
|
||||
|
||||
fputs(message, stderr);
|
||||
}
|
||||
@ -388,16 +388,16 @@ void old_keyfile_warning(void)
|
||||
void pgp_fingerprints(void)
|
||||
{
|
||||
fputs("These are the fingerprints of the PuTTY PGP Master Keys. They can\n"
|
||||
"be used to establish a trust path from this executable to another\n"
|
||||
"one. See the manual for more information.\n"
|
||||
"(Note: these fingerprints have nothing to do with SSH!)\n"
|
||||
"\n"
|
||||
"PuTTY Master Key as of " PGP_MASTER_KEY_YEAR
|
||||
"be used to establish a trust path from this executable to another\n"
|
||||
"one. See the manual for more information.\n"
|
||||
"(Note: these fingerprints have nothing to do with SSH!)\n"
|
||||
"\n"
|
||||
"PuTTY Master Key as of " PGP_MASTER_KEY_YEAR
|
||||
" (" PGP_MASTER_KEY_DETAILS "):\n"
|
||||
" " PGP_MASTER_KEY_FP "\n\n"
|
||||
"Previous Master Key (" PGP_PREV_MASTER_KEY_YEAR
|
||||
" " PGP_MASTER_KEY_FP "\n\n"
|
||||
"Previous Master Key (" PGP_PREV_MASTER_KEY_YEAR
|
||||
", " PGP_PREV_MASTER_KEY_DETAILS "):\n"
|
||||
" " PGP_PREV_MASTER_KEY_FP "\n", stdout);
|
||||
" " PGP_PREV_MASTER_KEY_FP "\n", stdout);
|
||||
}
|
||||
|
||||
static void console_logging_error(LogPolicy *lp, const char *string)
|
||||
@ -437,8 +437,8 @@ int console_get_userpass_input(prompts_t *p)
|
||||
* Zero all the results, in case we abort half-way through.
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int)p->n_prompts; i++)
|
||||
int i;
|
||||
for (i = 0; i < (int)p->n_prompts; i++)
|
||||
prompt_set_result(p->prompts[i], "");
|
||||
}
|
||||
|
||||
@ -449,24 +449,24 @@ int console_get_userpass_input(prompts_t *p)
|
||||
* need to ensure that we're able to get the answers.
|
||||
*/
|
||||
if (p->n_prompts) {
|
||||
if (console_batch_mode)
|
||||
return 0;
|
||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
if (hin == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "Cannot get standard input handle\n");
|
||||
cleanup_exit(1);
|
||||
}
|
||||
if (console_batch_mode)
|
||||
return 0;
|
||||
hin = GetStdHandle(STD_INPUT_HANDLE);
|
||||
if (hin == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "Cannot get standard input handle\n");
|
||||
cleanup_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* And if we have anything to print, we need standard output.
|
||||
*/
|
||||
if ((p->name_reqd && p->name) || p->instruction || p->n_prompts) {
|
||||
hout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hout == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "Cannot get standard output handle\n");
|
||||
cleanup_exit(1);
|
||||
}
|
||||
hout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (hout == INVALID_HANDLE_VALUE) {
|
||||
fprintf(stderr, "Cannot get standard output handle\n");
|
||||
cleanup_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -474,34 +474,34 @@ int console_get_userpass_input(prompts_t *p)
|
||||
*/
|
||||
/* We only print the `name' caption if we have to... */
|
||||
if (p->name_reqd && p->name) {
|
||||
ptrlen plname = ptrlen_from_asciz(p->name);
|
||||
console_write(hout, plname);
|
||||
ptrlen plname = ptrlen_from_asciz(p->name);
|
||||
console_write(hout, plname);
|
||||
if (!ptrlen_endswith(plname, PTRLEN_LITERAL("\n"), NULL))
|
||||
console_write(hout, PTRLEN_LITERAL("\n"));
|
||||
console_write(hout, PTRLEN_LITERAL("\n"));
|
||||
}
|
||||
/* ...but we always print any `instruction'. */
|
||||
if (p->instruction) {
|
||||
ptrlen plinst = ptrlen_from_asciz(p->instruction);
|
||||
console_write(hout, plinst);
|
||||
ptrlen plinst = ptrlen_from_asciz(p->instruction);
|
||||
console_write(hout, plinst);
|
||||
if (!ptrlen_endswith(plinst, PTRLEN_LITERAL("\n"), NULL))
|
||||
console_write(hout, PTRLEN_LITERAL("\n"));
|
||||
console_write(hout, PTRLEN_LITERAL("\n"));
|
||||
}
|
||||
|
||||
for (curr_prompt = 0; curr_prompt < p->n_prompts; curr_prompt++) {
|
||||
|
||||
DWORD savemode, newmode;
|
||||
DWORD savemode, newmode;
|
||||
size_t len;
|
||||
prompt_t *pr = p->prompts[curr_prompt];
|
||||
prompt_t *pr = p->prompts[curr_prompt];
|
||||
|
||||
GetConsoleMode(hin, &savemode);
|
||||
newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
|
||||
if (!pr->echo)
|
||||
newmode &= ~ENABLE_ECHO_INPUT;
|
||||
else
|
||||
newmode |= ENABLE_ECHO_INPUT;
|
||||
SetConsoleMode(hin, newmode);
|
||||
GetConsoleMode(hin, &savemode);
|
||||
newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
|
||||
if (!pr->echo)
|
||||
newmode &= ~ENABLE_ECHO_INPUT;
|
||||
else
|
||||
newmode |= ENABLE_ECHO_INPUT;
|
||||
SetConsoleMode(hin, newmode);
|
||||
|
||||
console_write(hout, ptrlen_from_asciz(pr->prompt));
|
||||
console_write(hout, ptrlen_from_asciz(pr->prompt));
|
||||
|
||||
len = 0;
|
||||
while (1) {
|
||||
@ -523,16 +523,16 @@ int console_get_userpass_input(prompts_t *p)
|
||||
}
|
||||
}
|
||||
|
||||
SetConsoleMode(hin, savemode);
|
||||
SetConsoleMode(hin, savemode);
|
||||
|
||||
if (!pr->echo)
|
||||
if (!pr->echo)
|
||||
console_write(hout, PTRLEN_LITERAL("\r\n"));
|
||||
|
||||
if (len == (size_t)-1) {
|
||||
return 0; /* failure due to read error */
|
||||
}
|
||||
|
||||
pr->result[len] = '\0';
|
||||
pr->result[len] = '\0';
|
||||
}
|
||||
|
||||
return 1; /* success */
|
||||
|
1870
windows/winctrls.c
1870
windows/winctrls.c
File diff suppressed because it is too large
Load Diff
@ -17,15 +17,15 @@ FontSpec *platform_default_fontspec(const char *name)
|
||||
Filename *platform_default_filename(const char *name)
|
||||
{
|
||||
if (!strcmp(name, "LogFileName"))
|
||||
return filename_from_str("putty.log");
|
||||
return filename_from_str("putty.log");
|
||||
else
|
||||
return filename_from_str("");
|
||||
return filename_from_str("");
|
||||
}
|
||||
|
||||
char *platform_default_s(const char *name)
|
||||
{
|
||||
if (!strcmp(name, "SerialLine"))
|
||||
return dupstr("COM1");
|
||||
return dupstr("COM1");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
906
windows/windlg.c
906
windows/windlg.c
File diff suppressed because it is too large
Load Diff
5450
windows/window.c
5450
windows/window.c
File diff suppressed because it is too large
Load Diff
268
windows/wingss.c
268
windows/wingss.c
@ -12,8 +12,8 @@
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
#define UNIX_EPOCH 11644473600ULL /* Seconds from Windows epoch */
|
||||
#define CNS_PERSEC 10000000ULL /* # 100ns per second */
|
||||
#define UNIX_EPOCH 11644473600ULL /* Seconds from Windows epoch */
|
||||
#define CNS_PERSEC 10000000ULL /* # 100ns per second */
|
||||
|
||||
/*
|
||||
* Note, as a special case, 0 relative to the Windows epoch (unspecified) maps
|
||||
@ -49,29 +49,29 @@ const struct keyvalwhere gsslibkeywords[] = {
|
||||
};
|
||||
|
||||
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
|
||||
AcquireCredentialsHandleA,
|
||||
(SEC_CHAR *, SEC_CHAR *, ULONG, PVOID,
|
||||
PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp));
|
||||
AcquireCredentialsHandleA,
|
||||
(SEC_CHAR *, SEC_CHAR *, ULONG, PVOID,
|
||||
PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp));
|
||||
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
|
||||
InitializeSecurityContextA,
|
||||
(PCredHandle, PCtxtHandle, SEC_CHAR *, ULONG, ULONG,
|
||||
ULONG, PSecBufferDesc, ULONG, PCtxtHandle,
|
||||
PSecBufferDesc, PULONG, PTimeStamp));
|
||||
InitializeSecurityContextA,
|
||||
(PCredHandle, PCtxtHandle, SEC_CHAR *, ULONG, ULONG,
|
||||
ULONG, PSecBufferDesc, ULONG, PCtxtHandle,
|
||||
PSecBufferDesc, PULONG, PTimeStamp));
|
||||
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
|
||||
FreeContextBuffer,
|
||||
(PVOID));
|
||||
FreeContextBuffer,
|
||||
(PVOID));
|
||||
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
|
||||
FreeCredentialsHandle,
|
||||
(PCredHandle));
|
||||
FreeCredentialsHandle,
|
||||
(PCredHandle));
|
||||
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
|
||||
DeleteSecurityContext,
|
||||
(PCtxtHandle));
|
||||
DeleteSecurityContext,
|
||||
(PCtxtHandle));
|
||||
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
|
||||
QueryContextAttributesA,
|
||||
(PCtxtHandle, ULONG, PVOID));
|
||||
QueryContextAttributesA,
|
||||
(PCtxtHandle, ULONG, PVOID));
|
||||
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
|
||||
MakeSignature,
|
||||
(PCtxtHandle, ULONG, PSecBufferDesc, ULONG));
|
||||
MakeSignature,
|
||||
(PCtxtHandle, ULONG, PSecBufferDesc, ULONG));
|
||||
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,
|
||||
VerifySignature,
|
||||
(PCtxtHandle, PSecBufferDesc, ULONG, PULONG));
|
||||
@ -118,19 +118,19 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
|
||||
/* MIT Kerberos GSSAPI implementation */
|
||||
module = NULL;
|
||||
if (RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\MIT\\Kerberos", ®key)
|
||||
== ERROR_SUCCESS) {
|
||||
DWORD type, size;
|
||||
LONG ret;
|
||||
char *buffer;
|
||||
== ERROR_SUCCESS) {
|
||||
DWORD type, size;
|
||||
LONG ret;
|
||||
char *buffer;
|
||||
|
||||
/* Find out the string length */
|
||||
/* Find out the string length */
|
||||
ret = RegQueryValueEx(regkey, "InstallDir", NULL, &type, NULL, &size);
|
||||
|
||||
if (ret == ERROR_SUCCESS && type == REG_SZ) {
|
||||
buffer = snewn(size + 20, char);
|
||||
ret = RegQueryValueEx(regkey, "InstallDir", NULL,
|
||||
&type, (LPBYTE)buffer, &size);
|
||||
if (ret == ERROR_SUCCESS && type == REG_SZ) {
|
||||
if (ret == ERROR_SUCCESS && type == REG_SZ) {
|
||||
buffer = snewn(size + 20, char);
|
||||
ret = RegQueryValueEx(regkey, "InstallDir", NULL,
|
||||
&type, (LPBYTE)buffer, &size);
|
||||
if (ret == ERROR_SUCCESS && type == REG_SZ) {
|
||||
strcat (buffer, "\\bin");
|
||||
if(p_AddDllDirectory) {
|
||||
/* Add MIT Kerberos' path to the DLL search path,
|
||||
@ -145,18 +145,18 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
|
||||
LOAD_LIBRARY_SEARCH_SYSTEM32 |
|
||||
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
|
||||
LOAD_LIBRARY_SEARCH_USER_DIRS);
|
||||
}
|
||||
sfree(buffer);
|
||||
}
|
||||
RegCloseKey(regkey);
|
||||
}
|
||||
sfree(buffer);
|
||||
}
|
||||
RegCloseKey(regkey);
|
||||
}
|
||||
if (module) {
|
||||
struct ssh_gss_library *lib =
|
||||
&list->libraries[list->nlibraries++];
|
||||
struct ssh_gss_library *lib =
|
||||
&list->libraries[list->nlibraries++];
|
||||
|
||||
lib->id = 0;
|
||||
lib->gsslogmsg = "Using GSSAPI from GSSAPI"MIT_KERB_SUFFIX".DLL";
|
||||
lib->handle = (void *)module;
|
||||
lib->id = 0;
|
||||
lib->gsslogmsg = "Using GSSAPI from GSSAPI"MIT_KERB_SUFFIX".DLL";
|
||||
lib->handle = (void *)module;
|
||||
|
||||
#define BIND_GSS_FN(name) \
|
||||
lib->u.gssapi.name = (t_gss_##name) GetProcAddress(module, "gss_" #name)
|
||||
@ -181,23 +181,23 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
|
||||
/* Microsoft SSPI Implementation */
|
||||
module = load_system32_dll("secur32.dll");
|
||||
if (module) {
|
||||
struct ssh_gss_library *lib =
|
||||
&list->libraries[list->nlibraries++];
|
||||
struct ssh_gss_library *lib =
|
||||
&list->libraries[list->nlibraries++];
|
||||
|
||||
lib->id = 1;
|
||||
lib->gsslogmsg = "Using SSPI from SECUR32.DLL";
|
||||
lib->handle = (void *)module;
|
||||
lib->id = 1;
|
||||
lib->gsslogmsg = "Using SSPI from SECUR32.DLL";
|
||||
lib->handle = (void *)module;
|
||||
|
||||
GET_WINDOWS_FUNCTION(module, AcquireCredentialsHandleA);
|
||||
GET_WINDOWS_FUNCTION(module, InitializeSecurityContextA);
|
||||
GET_WINDOWS_FUNCTION(module, FreeContextBuffer);
|
||||
GET_WINDOWS_FUNCTION(module, FreeCredentialsHandle);
|
||||
GET_WINDOWS_FUNCTION(module, DeleteSecurityContext);
|
||||
GET_WINDOWS_FUNCTION(module, QueryContextAttributesA);
|
||||
GET_WINDOWS_FUNCTION(module, MakeSignature);
|
||||
GET_WINDOWS_FUNCTION(module, AcquireCredentialsHandleA);
|
||||
GET_WINDOWS_FUNCTION(module, InitializeSecurityContextA);
|
||||
GET_WINDOWS_FUNCTION(module, FreeContextBuffer);
|
||||
GET_WINDOWS_FUNCTION(module, FreeCredentialsHandle);
|
||||
GET_WINDOWS_FUNCTION(module, DeleteSecurityContext);
|
||||
GET_WINDOWS_FUNCTION(module, QueryContextAttributesA);
|
||||
GET_WINDOWS_FUNCTION(module, MakeSignature);
|
||||
GET_WINDOWS_FUNCTION(module, VerifySignature);
|
||||
|
||||
ssh_sspi_bind_fns(lib);
|
||||
ssh_sspi_bind_fns(lib);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -234,13 +234,13 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
|
||||
LOAD_LIBRARY_SEARCH_USER_DIRS);
|
||||
}
|
||||
if (module) {
|
||||
struct ssh_gss_library *lib =
|
||||
&list->libraries[list->nlibraries++];
|
||||
struct ssh_gss_library *lib =
|
||||
&list->libraries[list->nlibraries++];
|
||||
|
||||
lib->id = 2;
|
||||
lib->gsslogmsg = dupprintf("Using GSSAPI from user-specified"
|
||||
" library '%s'", path);
|
||||
lib->handle = (void *)module;
|
||||
lib->id = 2;
|
||||
lib->gsslogmsg = dupprintf("Using GSSAPI from user-specified"
|
||||
" library '%s'", path);
|
||||
lib->handle = (void *)module;
|
||||
|
||||
#define BIND_GSS_FN(name) \
|
||||
lib->u.gssapi.name = (t_gss_##name) GetProcAddress(module, "gss_" #name)
|
||||
@ -280,19 +280,19 @@ void ssh_gss_cleanup(struct ssh_gss_liblist *list)
|
||||
* another SSH instance still using it.
|
||||
*/
|
||||
for (i = 0; i < list->nlibraries; i++) {
|
||||
FreeLibrary((HMODULE)list->libraries[i].handle);
|
||||
if (list->libraries[i].id == 2) {
|
||||
/* The 'custom' id involves a dynamically allocated message.
|
||||
* Note that we must cast away the 'const' to free it. */
|
||||
sfree((char *)list->libraries[i].gsslogmsg);
|
||||
}
|
||||
FreeLibrary((HMODULE)list->libraries[i].handle);
|
||||
if (list->libraries[i].id == 2) {
|
||||
/* The 'custom' id involves a dynamically allocated message.
|
||||
* Note that we must cast away the 'const' to free it. */
|
||||
sfree((char *)list->libraries[i].gsslogmsg);
|
||||
}
|
||||
}
|
||||
sfree(list->libraries);
|
||||
sfree(list);
|
||||
}
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_indicate_mech(struct ssh_gss_library *lib,
|
||||
Ssh_gss_buf *mech)
|
||||
Ssh_gss_buf *mech)
|
||||
{
|
||||
*mech = gss_mech_krb5;
|
||||
return SSH_GSS_OK;
|
||||
@ -300,13 +300,13 @@ static Ssh_gss_stat ssh_sspi_indicate_mech(struct ssh_gss_library *lib,
|
||||
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_import_name(struct ssh_gss_library *lib,
|
||||
char *host, Ssh_gss_name *srv_name)
|
||||
char *host, Ssh_gss_name *srv_name)
|
||||
{
|
||||
char *pStr;
|
||||
|
||||
/* Check hostname */
|
||||
if (host == NULL) return SSH_GSS_FAILURE;
|
||||
|
||||
|
||||
/* copy it into form host/FQDN */
|
||||
pStr = dupcat("host/", host, NULL);
|
||||
|
||||
@ -330,13 +330,13 @@ static Ssh_gss_stat ssh_sspi_acquire_cred(struct ssh_gss_library *lib,
|
||||
the current logged-in user */
|
||||
|
||||
winctx->maj_stat = p_AcquireCredentialsHandleA(NULL,
|
||||
"Kerberos",
|
||||
SECPKG_CRED_OUTBOUND,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&winctx->cred_handle,
|
||||
"Kerberos",
|
||||
SECPKG_CRED_OUTBOUND,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&winctx->cred_handle,
|
||||
NULL);
|
||||
|
||||
if (winctx->maj_stat != SEC_E_OK) {
|
||||
@ -407,10 +407,10 @@ static void localexp_to_exp_lifetime(TimeStamp *localexp,
|
||||
}
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_init_sec_context(struct ssh_gss_library *lib,
|
||||
Ssh_gss_ctx *ctx,
|
||||
Ssh_gss_name srv_name,
|
||||
int to_deleg,
|
||||
Ssh_gss_buf *recv_tok,
|
||||
Ssh_gss_ctx *ctx,
|
||||
Ssh_gss_name srv_name,
|
||||
int to_deleg,
|
||||
Ssh_gss_buf *recv_tok,
|
||||
Ssh_gss_buf *send_tok,
|
||||
time_t *expiry,
|
||||
unsigned long *lifetime)
|
||||
@ -421,23 +421,23 @@ static Ssh_gss_stat ssh_sspi_init_sec_context(struct ssh_gss_library *lib,
|
||||
SecBufferDesc output_desc={SECBUFFER_VERSION,1,&wsend_tok};
|
||||
SecBufferDesc input_desc ={SECBUFFER_VERSION,1,&wrecv_tok};
|
||||
unsigned long flags=ISC_REQ_MUTUAL_AUTH|ISC_REQ_REPLAY_DETECT|
|
||||
ISC_REQ_CONFIDENTIALITY|ISC_REQ_ALLOCATE_MEMORY;
|
||||
ISC_REQ_CONFIDENTIALITY|ISC_REQ_ALLOCATE_MEMORY;
|
||||
unsigned long ret_flags=0;
|
||||
TimeStamp localexp;
|
||||
|
||||
|
||||
/* check if we have to delegate ... */
|
||||
if (to_deleg) flags |= ISC_REQ_DELEGATE;
|
||||
winctx->maj_stat = p_InitializeSecurityContextA(&winctx->cred_handle,
|
||||
winctx->context_handle,
|
||||
(char*) srv_name,
|
||||
flags,
|
||||
0, /* reserved */
|
||||
SECURITY_NATIVE_DREP,
|
||||
&input_desc,
|
||||
0, /* reserved */
|
||||
&winctx->context,
|
||||
&output_desc,
|
||||
&ret_flags,
|
||||
winctx->context_handle,
|
||||
(char*) srv_name,
|
||||
flags,
|
||||
0, /* reserved */
|
||||
SECURITY_NATIVE_DREP,
|
||||
&input_desc,
|
||||
0, /* reserved */
|
||||
&winctx->context,
|
||||
&output_desc,
|
||||
&ret_flags,
|
||||
&localexp);
|
||||
|
||||
localexp_to_exp_lifetime(&localexp, expiry, lifetime);
|
||||
@ -446,16 +446,16 @@ static Ssh_gss_stat ssh_sspi_init_sec_context(struct ssh_gss_library *lib,
|
||||
winctx->context_handle = &winctx->context;
|
||||
send_tok->value = wsend_tok.pvBuffer;
|
||||
send_tok->length = wsend_tok.cbBuffer;
|
||||
|
||||
|
||||
/* check & return our status */
|
||||
if (winctx->maj_stat==SEC_E_OK) return SSH_GSS_S_COMPLETE;
|
||||
if (winctx->maj_stat==SEC_I_CONTINUE_NEEDED) return SSH_GSS_S_CONTINUE_NEEDED;
|
||||
|
||||
|
||||
return SSH_GSS_FAILURE;
|
||||
}
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_free_tok(struct ssh_gss_library *lib,
|
||||
Ssh_gss_buf *send_tok)
|
||||
Ssh_gss_buf *send_tok)
|
||||
{
|
||||
/* check input */
|
||||
if (send_tok == NULL) return SSH_GSS_FAILURE;
|
||||
@ -463,12 +463,12 @@ static Ssh_gss_stat ssh_sspi_free_tok(struct ssh_gss_library *lib,
|
||||
/* free Windows buffer */
|
||||
p_FreeContextBuffer(send_tok->value);
|
||||
SSH_GSS_CLEAR_BUF(send_tok);
|
||||
|
||||
|
||||
return SSH_GSS_OK;
|
||||
}
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_release_cred(struct ssh_gss_library *lib,
|
||||
Ssh_gss_ctx *ctx)
|
||||
Ssh_gss_ctx *ctx)
|
||||
{
|
||||
winSsh_gss_ctx *winctx= (winSsh_gss_ctx *) *ctx;
|
||||
|
||||
@ -488,7 +488,7 @@ static Ssh_gss_stat ssh_sspi_release_cred(struct ssh_gss_library *lib,
|
||||
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_release_name(struct ssh_gss_library *lib,
|
||||
Ssh_gss_name *srv_name)
|
||||
Ssh_gss_name *srv_name)
|
||||
{
|
||||
char *pStr= (char *) *srv_name;
|
||||
|
||||
@ -500,7 +500,7 @@ static Ssh_gss_stat ssh_sspi_release_name(struct ssh_gss_library *lib,
|
||||
}
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_display_status(struct ssh_gss_library *lib,
|
||||
Ssh_gss_ctx ctx, Ssh_gss_buf *buf)
|
||||
Ssh_gss_ctx ctx, Ssh_gss_buf *buf)
|
||||
{
|
||||
winSsh_gss_ctx *winctx = (winSsh_gss_ctx *) ctx;
|
||||
const char *msg;
|
||||
@ -511,48 +511,48 @@ static Ssh_gss_stat ssh_sspi_display_status(struct ssh_gss_library *lib,
|
||||
switch (winctx->maj_stat) {
|
||||
case SEC_E_OK: msg="SSPI status OK"; break;
|
||||
case SEC_E_INVALID_HANDLE: msg="The handle passed to the function"
|
||||
" is invalid.";
|
||||
break;
|
||||
" is invalid.";
|
||||
break;
|
||||
case SEC_E_TARGET_UNKNOWN: msg="The target was not recognized."; break;
|
||||
case SEC_E_LOGON_DENIED: msg="The logon failed."; break;
|
||||
case SEC_E_INTERNAL_ERROR: msg="The Local Security Authority cannot"
|
||||
" be contacted.";
|
||||
break;
|
||||
" be contacted.";
|
||||
break;
|
||||
case SEC_E_NO_CREDENTIALS: msg="No credentials are available in the"
|
||||
" security package.";
|
||||
break;
|
||||
" security package.";
|
||||
break;
|
||||
case SEC_E_NO_AUTHENTICATING_AUTHORITY:
|
||||
msg="No authority could be contacted for authentication."
|
||||
"The domain name of the authenticating party could be wrong,"
|
||||
" the domain could be unreachable, or there might have been"
|
||||
" a trust relationship failure.";
|
||||
break;
|
||||
msg="No authority could be contacted for authentication."
|
||||
"The domain name of the authenticating party could be wrong,"
|
||||
" the domain could be unreachable, or there might have been"
|
||||
" a trust relationship failure.";
|
||||
break;
|
||||
case SEC_E_INSUFFICIENT_MEMORY:
|
||||
msg="One or more of the SecBufferDesc structures passed as"
|
||||
" an OUT parameter has a buffer that is too small.";
|
||||
break;
|
||||
msg="One or more of the SecBufferDesc structures passed as"
|
||||
" an OUT parameter has a buffer that is too small.";
|
||||
break;
|
||||
case SEC_E_INVALID_TOKEN:
|
||||
msg="The error is due to a malformed input token, such as a"
|
||||
" token corrupted in transit, a token"
|
||||
" of incorrect size, or a token passed into the wrong"
|
||||
" security package. Passing a token to"
|
||||
" the wrong package can happen if client and server did not"
|
||||
" negotiate the proper security package.";
|
||||
break;
|
||||
msg="The error is due to a malformed input token, such as a"
|
||||
" token corrupted in transit, a token"
|
||||
" of incorrect size, or a token passed into the wrong"
|
||||
" security package. Passing a token to"
|
||||
" the wrong package can happen if client and server did not"
|
||||
" negotiate the proper security package.";
|
||||
break;
|
||||
default:
|
||||
msg = "Internal SSPI error";
|
||||
break;
|
||||
msg = "Internal SSPI error";
|
||||
break;
|
||||
}
|
||||
|
||||
buf->value = dupstr(msg);
|
||||
buf->length = strlen(buf->value);
|
||||
|
||||
|
||||
return SSH_GSS_OK;
|
||||
}
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_get_mic(struct ssh_gss_library *lib,
|
||||
Ssh_gss_ctx ctx, Ssh_gss_buf *buf,
|
||||
Ssh_gss_buf *hash)
|
||||
Ssh_gss_ctx ctx, Ssh_gss_buf *buf,
|
||||
Ssh_gss_buf *hash)
|
||||
{
|
||||
winSsh_gss_ctx *winctx= (winSsh_gss_ctx *) ctx;
|
||||
SecPkgContext_Sizes ContextSizes;
|
||||
@ -560,18 +560,18 @@ static Ssh_gss_stat ssh_sspi_get_mic(struct ssh_gss_library *lib,
|
||||
SecBuffer InputSecurityToken[2];
|
||||
|
||||
if (winctx == NULL) return SSH_GSS_FAILURE;
|
||||
|
||||
|
||||
winctx->maj_stat = 0;
|
||||
|
||||
memset(&ContextSizes, 0, sizeof(ContextSizes));
|
||||
|
||||
winctx->maj_stat = p_QueryContextAttributesA(&winctx->context,
|
||||
SECPKG_ATTR_SIZES,
|
||||
&ContextSizes);
|
||||
|
||||
SECPKG_ATTR_SIZES,
|
||||
&ContextSizes);
|
||||
|
||||
if (winctx->maj_stat != SEC_E_OK ||
|
||||
ContextSizes.cbMaxSignature == 0)
|
||||
return winctx->maj_stat;
|
||||
ContextSizes.cbMaxSignature == 0)
|
||||
return winctx->maj_stat;
|
||||
|
||||
InputBufferDescriptor.cBuffers = 2;
|
||||
InputBufferDescriptor.pBuffers = InputSecurityToken;
|
||||
@ -584,13 +584,13 @@ static Ssh_gss_stat ssh_sspi_get_mic(struct ssh_gss_library *lib,
|
||||
InputSecurityToken[1].pvBuffer = snewn(ContextSizes.cbMaxSignature, char);
|
||||
|
||||
winctx->maj_stat = p_MakeSignature(&winctx->context,
|
||||
0,
|
||||
&InputBufferDescriptor,
|
||||
0);
|
||||
0,
|
||||
&InputBufferDescriptor,
|
||||
0);
|
||||
|
||||
if (winctx->maj_stat == SEC_E_OK) {
|
||||
hash->length = InputSecurityToken[1].cbBuffer;
|
||||
hash->value = InputSecurityToken[1].pvBuffer;
|
||||
hash->length = InputSecurityToken[1].cbBuffer;
|
||||
hash->value = InputSecurityToken[1].pvBuffer;
|
||||
}
|
||||
|
||||
return winctx->maj_stat;
|
||||
@ -627,7 +627,7 @@ static Ssh_gss_stat ssh_sspi_verify_mic(struct ssh_gss_library *lib,
|
||||
}
|
||||
|
||||
static Ssh_gss_stat ssh_sspi_free_mic(struct ssh_gss_library *lib,
|
||||
Ssh_gss_buf *hash)
|
||||
Ssh_gss_buf *hash)
|
||||
{
|
||||
sfree(hash->value);
|
||||
return SSH_GSS_OK;
|
||||
|
@ -9,14 +9,14 @@
|
||||
* data, the subthread sets an event object which is picked up by
|
||||
* the main thread, and the main thread then sets an event in
|
||||
* return to instruct the subthread to resume reading.
|
||||
*
|
||||
*
|
||||
* Output works precisely the other way round, in a second
|
||||
* subthread. The output subthread should not be attempting to
|
||||
* write all the time, because it hasn't always got data _to_
|
||||
* write; so the output thread waits for an event object notifying
|
||||
* it to _attempt_ a write, and then it sets an event in return
|
||||
* when one completes.
|
||||
*
|
||||
*
|
||||
* (It's terribly annoying having to spawn a subthread for each
|
||||
* direction of each handle. Technically it isn't necessary for
|
||||
* serial ports, since we could use overlapped I/O within the main
|
||||
@ -47,7 +47,7 @@ struct handle_generic {
|
||||
/*
|
||||
* Initial fields common to both handle_input and handle_output
|
||||
* structures.
|
||||
*
|
||||
*
|
||||
* The three HANDLEs are set up at initialisation time and are
|
||||
* thereafter read-only to both main thread and subthread.
|
||||
* `moribund' is only used by the main thread; `done' is
|
||||
@ -55,14 +55,14 @@ struct handle_generic {
|
||||
* subthread. `defunct' and `busy' are used only by the main
|
||||
* thread.
|
||||
*/
|
||||
HANDLE h; /* the handle itself */
|
||||
HANDLE ev_to_main; /* event used to signal main thread */
|
||||
HANDLE ev_from_main; /* event used to signal back to us */
|
||||
HANDLE h; /* the handle itself */
|
||||
HANDLE ev_to_main; /* event used to signal main thread */
|
||||
HANDLE ev_from_main; /* event used to signal back to us */
|
||||
bool moribund; /* are we going to kill this soon? */
|
||||
bool done; /* request subthread to terminate */
|
||||
bool defunct; /* has the subthread already gone? */
|
||||
bool busy; /* operation currently in progress? */
|
||||
void *privdata; /* for client to remember who they are */
|
||||
void *privdata; /* for client to remember who they are */
|
||||
};
|
||||
|
||||
typedef enum { HT_INPUT, HT_OUTPUT, HT_FOREIGN } HandleType;
|
||||
@ -78,14 +78,14 @@ struct handle_input {
|
||||
/*
|
||||
* Copy of the handle_generic structure.
|
||||
*/
|
||||
HANDLE h; /* the handle itself */
|
||||
HANDLE ev_to_main; /* event used to signal main thread */
|
||||
HANDLE ev_from_main; /* event used to signal back to us */
|
||||
HANDLE h; /* the handle itself */
|
||||
HANDLE ev_to_main; /* event used to signal main thread */
|
||||
HANDLE ev_from_main; /* event used to signal back to us */
|
||||
bool moribund; /* are we going to kill this soon? */
|
||||
bool done; /* request subthread to terminate */
|
||||
bool defunct; /* has the subthread already gone? */
|
||||
bool busy; /* operation currently in progress? */
|
||||
void *privdata; /* for client to remember who they are */
|
||||
void *privdata; /* for client to remember who they are */
|
||||
|
||||
/*
|
||||
* Data set at initialisation and then read-only.
|
||||
@ -96,9 +96,9 @@ struct handle_input {
|
||||
* Data set by the input thread before signalling ev_to_main,
|
||||
* and read by the main thread after receiving that signal.
|
||||
*/
|
||||
char buffer[4096]; /* the data read from the handle */
|
||||
DWORD len; /* how much data that was */
|
||||
int readerr; /* lets us know about read errors */
|
||||
char buffer[4096]; /* the data read from the handle */
|
||||
DWORD len; /* how much data that was */
|
||||
int readerr; /* lets us know about read errors */
|
||||
|
||||
/*
|
||||
* Callback function called by this module when data arrives on
|
||||
@ -119,52 +119,52 @@ static DWORD WINAPI handle_input_threadfunc(void *param)
|
||||
int readlen;
|
||||
|
||||
if (ctx->flags & HANDLE_FLAG_OVERLAPPED) {
|
||||
povl = &ovl;
|
||||
oev = CreateEvent(NULL, true, false, NULL);
|
||||
povl = &ovl;
|
||||
oev = CreateEvent(NULL, true, false, NULL);
|
||||
} else {
|
||||
povl = NULL;
|
||||
povl = NULL;
|
||||
}
|
||||
|
||||
if (ctx->flags & HANDLE_FLAG_UNITBUFFER)
|
||||
readlen = 1;
|
||||
readlen = 1;
|
||||
else
|
||||
readlen = sizeof(ctx->buffer);
|
||||
readlen = sizeof(ctx->buffer);
|
||||
|
||||
while (1) {
|
||||
if (povl) {
|
||||
memset(povl, 0, sizeof(OVERLAPPED));
|
||||
povl->hEvent = oev;
|
||||
}
|
||||
readret = ReadFile(ctx->h, ctx->buffer,readlen, &ctx->len, povl);
|
||||
if (!readret)
|
||||
ctx->readerr = GetLastError();
|
||||
else
|
||||
ctx->readerr = 0;
|
||||
if (povl && !readret && ctx->readerr == ERROR_IO_PENDING) {
|
||||
WaitForSingleObject(povl->hEvent, INFINITE);
|
||||
readret = GetOverlappedResult(ctx->h, povl, &ctx->len, false);
|
||||
if (!readret)
|
||||
ctx->readerr = GetLastError();
|
||||
else
|
||||
ctx->readerr = 0;
|
||||
}
|
||||
if (povl) {
|
||||
memset(povl, 0, sizeof(OVERLAPPED));
|
||||
povl->hEvent = oev;
|
||||
}
|
||||
readret = ReadFile(ctx->h, ctx->buffer,readlen, &ctx->len, povl);
|
||||
if (!readret)
|
||||
ctx->readerr = GetLastError();
|
||||
else
|
||||
ctx->readerr = 0;
|
||||
if (povl && !readret && ctx->readerr == ERROR_IO_PENDING) {
|
||||
WaitForSingleObject(povl->hEvent, INFINITE);
|
||||
readret = GetOverlappedResult(ctx->h, povl, &ctx->len, false);
|
||||
if (!readret)
|
||||
ctx->readerr = GetLastError();
|
||||
else
|
||||
ctx->readerr = 0;
|
||||
}
|
||||
|
||||
if (!readret) {
|
||||
/*
|
||||
* Windows apparently sends ERROR_BROKEN_PIPE when a
|
||||
* pipe we're reading from is closed normally from the
|
||||
* writing end. This is ludicrous; if that situation
|
||||
* isn't a natural EOF, _nothing_ is. So if we get that
|
||||
* particular error, we pretend it's EOF.
|
||||
*/
|
||||
if (ctx->readerr == ERROR_BROKEN_PIPE)
|
||||
ctx->readerr = 0;
|
||||
ctx->len = 0;
|
||||
}
|
||||
if (!readret) {
|
||||
/*
|
||||
* Windows apparently sends ERROR_BROKEN_PIPE when a
|
||||
* pipe we're reading from is closed normally from the
|
||||
* writing end. This is ludicrous; if that situation
|
||||
* isn't a natural EOF, _nothing_ is. So if we get that
|
||||
* particular error, we pretend it's EOF.
|
||||
*/
|
||||
if (ctx->readerr == ERROR_BROKEN_PIPE)
|
||||
ctx->readerr = 0;
|
||||
ctx->len = 0;
|
||||
}
|
||||
|
||||
if (readret && ctx->len == 0 &&
|
||||
(ctx->flags & HANDLE_FLAG_IGNOREEOF))
|
||||
continue;
|
||||
if (readret && ctx->len == 0 &&
|
||||
(ctx->flags & HANDLE_FLAG_IGNOREEOF))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we just set ctx->len to 0, that means the read operation
|
||||
@ -176,13 +176,13 @@ static DWORD WINAPI handle_input_threadfunc(void *param)
|
||||
*/
|
||||
finished = (ctx->len == 0);
|
||||
|
||||
SetEvent(ctx->ev_to_main);
|
||||
SetEvent(ctx->ev_to_main);
|
||||
|
||||
if (finished)
|
||||
break;
|
||||
if (finished)
|
||||
break;
|
||||
|
||||
WaitForSingleObject(ctx->ev_from_main, INFINITE);
|
||||
if (ctx->done) {
|
||||
WaitForSingleObject(ctx->ev_from_main, INFINITE);
|
||||
if (ctx->done) {
|
||||
/*
|
||||
* The main thread has asked us to shut down. Send back an
|
||||
* event indicating that we've done so. Hereafter we must
|
||||
@ -195,7 +195,7 @@ static DWORD WINAPI handle_input_threadfunc(void *param)
|
||||
}
|
||||
|
||||
if (povl)
|
||||
CloseHandle(oev);
|
||||
CloseHandle(oev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -208,7 +208,7 @@ static DWORD WINAPI handle_input_threadfunc(void *param)
|
||||
static void handle_throttle(struct handle_input *ctx, int backlog)
|
||||
{
|
||||
if (ctx->defunct)
|
||||
return;
|
||||
return;
|
||||
|
||||
/*
|
||||
* If there's a read operation already in progress, do nothing:
|
||||
@ -216,15 +216,15 @@ static void handle_throttle(struct handle_input *ctx, int backlog)
|
||||
* position to make a better decision.
|
||||
*/
|
||||
if (ctx->busy)
|
||||
return;
|
||||
return;
|
||||
|
||||
/*
|
||||
* Otherwise, we must decide whether to start a new read based
|
||||
* on the size of the backlog.
|
||||
*/
|
||||
if (backlog < MAX_BACKLOG) {
|
||||
SetEvent(ctx->ev_from_main);
|
||||
ctx->busy = true;
|
||||
SetEvent(ctx->ev_from_main);
|
||||
ctx->busy = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,14 +239,14 @@ struct handle_output {
|
||||
/*
|
||||
* Copy of the handle_generic structure.
|
||||
*/
|
||||
HANDLE h; /* the handle itself */
|
||||
HANDLE ev_to_main; /* event used to signal main thread */
|
||||
HANDLE ev_from_main; /* event used to signal back to us */
|
||||
HANDLE h; /* the handle itself */
|
||||
HANDLE ev_to_main; /* event used to signal main thread */
|
||||
HANDLE ev_from_main; /* event used to signal back to us */
|
||||
bool moribund; /* are we going to kill this soon? */
|
||||
bool done; /* request subthread to terminate */
|
||||
bool defunct; /* has the subthread already gone? */
|
||||
bool busy; /* operation currently in progress? */
|
||||
void *privdata; /* for client to remember who they are */
|
||||
void *privdata; /* for client to remember who they are */
|
||||
|
||||
/*
|
||||
* Data set at initialisation and then read-only.
|
||||
@ -258,19 +258,19 @@ struct handle_output {
|
||||
* and read by the input thread after receiving that signal.
|
||||
*/
|
||||
const char *buffer; /* the data to write */
|
||||
DWORD len; /* how much data there is */
|
||||
DWORD len; /* how much data there is */
|
||||
|
||||
/*
|
||||
* Data set by the input thread before signalling ev_to_main,
|
||||
* and read by the main thread after receiving that signal.
|
||||
*/
|
||||
DWORD lenwritten; /* how much data we actually wrote */
|
||||
int writeerr; /* return value from WriteFile */
|
||||
DWORD lenwritten; /* how much data we actually wrote */
|
||||
int writeerr; /* return value from WriteFile */
|
||||
|
||||
/*
|
||||
* Data only ever read or written by the main thread.
|
||||
*/
|
||||
bufchain queued_data; /* data still waiting to be written */
|
||||
bufchain queued_data; /* data still waiting to be written */
|
||||
enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof;
|
||||
|
||||
/*
|
||||
@ -288,46 +288,46 @@ static DWORD WINAPI handle_output_threadfunc(void *param)
|
||||
bool writeret;
|
||||
|
||||
if (ctx->flags & HANDLE_FLAG_OVERLAPPED) {
|
||||
povl = &ovl;
|
||||
oev = CreateEvent(NULL, true, false, NULL);
|
||||
povl = &ovl;
|
||||
oev = CreateEvent(NULL, true, false, NULL);
|
||||
} else {
|
||||
povl = NULL;
|
||||
povl = NULL;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
WaitForSingleObject(ctx->ev_from_main, INFINITE);
|
||||
if (ctx->done) {
|
||||
WaitForSingleObject(ctx->ev_from_main, INFINITE);
|
||||
if (ctx->done) {
|
||||
/*
|
||||
* The main thread has asked us to shut down. Send back an
|
||||
* event indicating that we've done so. Hereafter we must
|
||||
* not touch ctx at all, because the main thread might
|
||||
* have freed it.
|
||||
*/
|
||||
SetEvent(ctx->ev_to_main);
|
||||
break;
|
||||
}
|
||||
if (povl) {
|
||||
memset(povl, 0, sizeof(OVERLAPPED));
|
||||
povl->hEvent = oev;
|
||||
}
|
||||
SetEvent(ctx->ev_to_main);
|
||||
break;
|
||||
}
|
||||
if (povl) {
|
||||
memset(povl, 0, sizeof(OVERLAPPED));
|
||||
povl->hEvent = oev;
|
||||
}
|
||||
|
||||
writeret = WriteFile(ctx->h, ctx->buffer, ctx->len,
|
||||
&ctx->lenwritten, povl);
|
||||
if (!writeret)
|
||||
ctx->writeerr = GetLastError();
|
||||
else
|
||||
ctx->writeerr = 0;
|
||||
if (povl && !writeret && GetLastError() == ERROR_IO_PENDING) {
|
||||
writeret = GetOverlappedResult(ctx->h, povl,
|
||||
&ctx->lenwritten, true);
|
||||
if (!writeret)
|
||||
ctx->writeerr = GetLastError();
|
||||
else
|
||||
ctx->writeerr = 0;
|
||||
}
|
||||
writeret = WriteFile(ctx->h, ctx->buffer, ctx->len,
|
||||
&ctx->lenwritten, povl);
|
||||
if (!writeret)
|
||||
ctx->writeerr = GetLastError();
|
||||
else
|
||||
ctx->writeerr = 0;
|
||||
if (povl && !writeret && GetLastError() == ERROR_IO_PENDING) {
|
||||
writeret = GetOverlappedResult(ctx->h, povl,
|
||||
&ctx->lenwritten, true);
|
||||
if (!writeret)
|
||||
ctx->writeerr = GetLastError();
|
||||
else
|
||||
ctx->writeerr = 0;
|
||||
}
|
||||
|
||||
SetEvent(ctx->ev_to_main);
|
||||
if (!writeret) {
|
||||
SetEvent(ctx->ev_to_main);
|
||||
if (!writeret) {
|
||||
/*
|
||||
* The write operation has suffered an error. Telling that
|
||||
* to the main thread will cause it to set its 'defunct'
|
||||
@ -335,12 +335,12 @@ static DWORD WINAPI handle_output_threadfunc(void *param)
|
||||
* opportunity, so we must not touch ctx at all after
|
||||
* this.
|
||||
*/
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (povl)
|
||||
CloseHandle(oev);
|
||||
CloseHandle(oev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -348,11 +348,11 @@ static DWORD WINAPI handle_output_threadfunc(void *param)
|
||||
static void handle_try_output(struct handle_output *ctx)
|
||||
{
|
||||
if (!ctx->busy && bufchain_size(&ctx->queued_data)) {
|
||||
ptrlen data = bufchain_prefix(&ctx->queued_data);
|
||||
ctx->buffer = data.ptr;
|
||||
ctx->len = min(data.len, ~(DWORD)0);
|
||||
SetEvent(ctx->ev_from_main);
|
||||
ctx->busy = true;
|
||||
ptrlen data = bufchain_prefix(&ctx->queued_data);
|
||||
ctx->buffer = data.ptr;
|
||||
ctx->len = min(data.len, ~(DWORD)0);
|
||||
SetEvent(ctx->ev_from_main);
|
||||
ctx->busy = true;
|
||||
} else if (!ctx->busy && bufchain_size(&ctx->queued_data) == 0 &&
|
||||
ctx->outgoingeof == EOF_PENDING) {
|
||||
CloseHandle(ctx->h);
|
||||
@ -372,14 +372,14 @@ struct handle_foreign {
|
||||
/*
|
||||
* Copy of the handle_generic structure.
|
||||
*/
|
||||
HANDLE h; /* the handle itself */
|
||||
HANDLE ev_to_main; /* event used to signal main thread */
|
||||
HANDLE ev_from_main; /* event used to signal back to us */
|
||||
HANDLE h; /* the handle itself */
|
||||
HANDLE ev_to_main; /* event used to signal main thread */
|
||||
HANDLE ev_from_main; /* event used to signal back to us */
|
||||
bool moribund; /* are we going to kill this soon? */
|
||||
bool done; /* request subthread to terminate */
|
||||
bool defunct; /* has the subthread already gone? */
|
||||
bool busy; /* operation currently in progress? */
|
||||
void *privdata; /* for client to remember who they are */
|
||||
void *privdata; /* for client to remember who they are */
|
||||
|
||||
/*
|
||||
* Our own data, just consisting of knowledge of who to call back.
|
||||
@ -395,10 +395,10 @@ struct handle_foreign {
|
||||
struct handle {
|
||||
HandleType type;
|
||||
union {
|
||||
struct handle_generic g;
|
||||
struct handle_input i;
|
||||
struct handle_output o;
|
||||
struct handle_foreign f;
|
||||
struct handle_generic g;
|
||||
struct handle_input i;
|
||||
struct handle_output o;
|
||||
struct handle_foreign f;
|
||||
} u;
|
||||
};
|
||||
|
||||
@ -410,11 +410,11 @@ static int handle_cmp_evtomain(void *av, void *bv)
|
||||
struct handle *b = (struct handle *)bv;
|
||||
|
||||
if ((uintptr_t)a->u.g.ev_to_main < (uintptr_t)b->u.g.ev_to_main)
|
||||
return -1;
|
||||
return -1;
|
||||
else if ((uintptr_t)a->u.g.ev_to_main > (uintptr_t)b->u.g.ev_to_main)
|
||||
return +1;
|
||||
return +1;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_find_evtomain(void *av, void *bv)
|
||||
@ -423,15 +423,15 @@ static int handle_find_evtomain(void *av, void *bv)
|
||||
struct handle *b = (struct handle *)bv;
|
||||
|
||||
if ((uintptr_t)*a < (uintptr_t)b->u.g.ev_to_main)
|
||||
return -1;
|
||||
return -1;
|
||||
else if ((uintptr_t)*a > (uintptr_t)b->u.g.ev_to_main)
|
||||
return +1;
|
||||
return +1;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
|
||||
void *privdata, int flags)
|
||||
void *privdata, int flags)
|
||||
{
|
||||
struct handle *h = snew(struct handle);
|
||||
DWORD in_threadid; /* required for Win9x */
|
||||
@ -448,18 +448,18 @@ struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
|
||||
h->u.i.flags = flags;
|
||||
|
||||
if (!handles_by_evtomain)
|
||||
handles_by_evtomain = newtree234(handle_cmp_evtomain);
|
||||
handles_by_evtomain = newtree234(handle_cmp_evtomain);
|
||||
add234(handles_by_evtomain, h);
|
||||
|
||||
CreateThread(NULL, 0, handle_input_threadfunc,
|
||||
&h->u.i, 0, &in_threadid);
|
||||
&h->u.i, 0, &in_threadid);
|
||||
h->u.i.busy = true;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
|
||||
void *privdata, int flags)
|
||||
void *privdata, int flags)
|
||||
{
|
||||
struct handle *h = snew(struct handle);
|
||||
DWORD out_threadid; /* required for Win9x */
|
||||
@ -479,11 +479,11 @@ struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
|
||||
h->u.o.flags = flags;
|
||||
|
||||
if (!handles_by_evtomain)
|
||||
handles_by_evtomain = newtree234(handle_cmp_evtomain);
|
||||
handles_by_evtomain = newtree234(handle_cmp_evtomain);
|
||||
add234(handles_by_evtomain, h);
|
||||
|
||||
CreateThread(NULL, 0, handle_output_threadfunc,
|
||||
&h->u.o, 0, &out_threadid);
|
||||
&h->u.o, 0, &out_threadid);
|
||||
|
||||
return h;
|
||||
}
|
||||
@ -506,7 +506,7 @@ struct handle *handle_add_foreign_event(HANDLE event,
|
||||
h->u.f.busy = true;
|
||||
|
||||
if (!handles_by_evtomain)
|
||||
handles_by_evtomain = newtree234(handle_cmp_evtomain);
|
||||
handles_by_evtomain = newtree234(handle_cmp_evtomain);
|
||||
add234(handles_by_evtomain, h);
|
||||
|
||||
return h;
|
||||
@ -551,12 +551,12 @@ HANDLE *handle_get_events(int *nevents)
|
||||
ret = NULL;
|
||||
n = size = 0;
|
||||
if (handles_by_evtomain) {
|
||||
for (i = 0; (h = index234(handles_by_evtomain, i)) != NULL; i++) {
|
||||
if (h->u.g.busy) {
|
||||
for (i = 0; (h = index234(handles_by_evtomain, i)) != NULL; i++) {
|
||||
if (h->u.g.busy) {
|
||||
sgrowarray(ret, size, n);
|
||||
ret[n++] = h->u.g.ev_to_main;
|
||||
}
|
||||
}
|
||||
ret[n++] = h->u.g.ev_to_main;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*nevents = n;
|
||||
@ -566,7 +566,7 @@ HANDLE *handle_get_events(int *nevents)
|
||||
static void handle_destroy(struct handle *h)
|
||||
{
|
||||
if (h->type == HT_OUTPUT)
|
||||
bufchain_clear(&h->u.o.queued_data);
|
||||
bufchain_clear(&h->u.o.queued_data);
|
||||
CloseHandle(h->u.g.ev_from_main);
|
||||
CloseHandle(h->u.g.ev_to_main);
|
||||
del234(handles_by_evtomain, h);
|
||||
@ -587,24 +587,24 @@ void handle_free(struct handle *h)
|
||||
* invalid memory after we free its context from under it. So
|
||||
* we set the moribund flag, which will be noticed next time
|
||||
* an operation completes.
|
||||
*/
|
||||
h->u.g.moribund = true;
|
||||
*/
|
||||
h->u.g.moribund = true;
|
||||
} else if (h->u.g.defunct) {
|
||||
/*
|
||||
* There isn't even a subthread; we can go straight to
|
||||
* handle_destroy.
|
||||
*/
|
||||
handle_destroy(h);
|
||||
/*
|
||||
* There isn't even a subthread; we can go straight to
|
||||
* handle_destroy.
|
||||
*/
|
||||
handle_destroy(h);
|
||||
} else {
|
||||
/*
|
||||
* The subthread is alive but not busy, so we now signal it
|
||||
* to die. Set the moribund flag to indicate that it will
|
||||
* want destroying after that.
|
||||
*/
|
||||
h->u.g.moribund = true;
|
||||
h->u.g.done = true;
|
||||
h->u.g.busy = true;
|
||||
SetEvent(h->u.g.ev_from_main);
|
||||
/*
|
||||
* The subthread is alive but not busy, so we now signal it
|
||||
* to die. Set the moribund flag to indicate that it will
|
||||
* want destroying after that.
|
||||
*/
|
||||
h->u.g.moribund = true;
|
||||
h->u.g.done = true;
|
||||
h->u.g.busy = true;
|
||||
SetEvent(h->u.g.ev_from_main);
|
||||
}
|
||||
}
|
||||
|
||||
@ -615,79 +615,79 @@ void handle_got_event(HANDLE event)
|
||||
assert(handles_by_evtomain);
|
||||
h = find234(handles_by_evtomain, &event, handle_find_evtomain);
|
||||
if (!h) {
|
||||
/*
|
||||
* This isn't an error condition. If two or more event
|
||||
* objects were signalled during the same select operation,
|
||||
* and processing of the first caused the second handle to
|
||||
* be closed, then it will sometimes happen that we receive
|
||||
* an event notification here for a handle which is already
|
||||
* deceased. In that situation we simply do nothing.
|
||||
*/
|
||||
return;
|
||||
/*
|
||||
* This isn't an error condition. If two or more event
|
||||
* objects were signalled during the same select operation,
|
||||
* and processing of the first caused the second handle to
|
||||
* be closed, then it will sometimes happen that we receive
|
||||
* an event notification here for a handle which is already
|
||||
* deceased. In that situation we simply do nothing.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (h->u.g.moribund) {
|
||||
/*
|
||||
* A moribund handle is one which we have either already
|
||||
* signalled to die, or are waiting until its current I/O op
|
||||
* completes to do so. Either way, it's treated as already
|
||||
* dead from the external user's point of view, so we ignore
|
||||
* the actual I/O result. We just signal the thread to die if
|
||||
* we haven't yet done so, or destroy the handle if not.
|
||||
*/
|
||||
if (h->u.g.done) {
|
||||
handle_destroy(h);
|
||||
} else {
|
||||
h->u.g.done = true;
|
||||
h->u.g.busy = true;
|
||||
SetEvent(h->u.g.ev_from_main);
|
||||
}
|
||||
return;
|
||||
/*
|
||||
* A moribund handle is one which we have either already
|
||||
* signalled to die, or are waiting until its current I/O op
|
||||
* completes to do so. Either way, it's treated as already
|
||||
* dead from the external user's point of view, so we ignore
|
||||
* the actual I/O result. We just signal the thread to die if
|
||||
* we haven't yet done so, or destroy the handle if not.
|
||||
*/
|
||||
if (h->u.g.done) {
|
||||
handle_destroy(h);
|
||||
} else {
|
||||
h->u.g.done = true;
|
||||
h->u.g.busy = true;
|
||||
SetEvent(h->u.g.ev_from_main);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (h->type) {
|
||||
int backlog;
|
||||
int backlog;
|
||||
|
||||
case HT_INPUT:
|
||||
h->u.i.busy = false;
|
||||
h->u.i.busy = false;
|
||||
|
||||
/*
|
||||
* A signal on an input handle means data has arrived.
|
||||
*/
|
||||
if (h->u.i.len == 0) {
|
||||
/*
|
||||
* EOF, or (nearly equivalently) read error.
|
||||
*/
|
||||
h->u.i.defunct = true;
|
||||
h->u.i.gotdata(h, NULL, 0, h->u.i.readerr);
|
||||
} else {
|
||||
backlog = h->u.i.gotdata(h, h->u.i.buffer, h->u.i.len, 0);
|
||||
handle_throttle(&h->u.i, backlog);
|
||||
}
|
||||
/*
|
||||
* A signal on an input handle means data has arrived.
|
||||
*/
|
||||
if (h->u.i.len == 0) {
|
||||
/*
|
||||
* EOF, or (nearly equivalently) read error.
|
||||
*/
|
||||
h->u.i.defunct = true;
|
||||
h->u.i.gotdata(h, NULL, 0, h->u.i.readerr);
|
||||
} else {
|
||||
backlog = h->u.i.gotdata(h, h->u.i.buffer, h->u.i.len, 0);
|
||||
handle_throttle(&h->u.i, backlog);
|
||||
}
|
||||
break;
|
||||
|
||||
case HT_OUTPUT:
|
||||
h->u.o.busy = false;
|
||||
h->u.o.busy = false;
|
||||
|
||||
/*
|
||||
* A signal on an output handle means we have completed a
|
||||
* write. Call the callback to indicate that the output
|
||||
* buffer size has decreased, or to indicate an error.
|
||||
*/
|
||||
if (h->u.o.writeerr) {
|
||||
/*
|
||||
* Write error. Send a negative value to the callback,
|
||||
* and mark the thread as defunct (because the output
|
||||
* thread is terminating by now).
|
||||
*/
|
||||
h->u.o.defunct = true;
|
||||
h->u.o.sentdata(h, 0, h->u.o.writeerr);
|
||||
} else {
|
||||
bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten);
|
||||
/*
|
||||
* A signal on an output handle means we have completed a
|
||||
* write. Call the callback to indicate that the output
|
||||
* buffer size has decreased, or to indicate an error.
|
||||
*/
|
||||
if (h->u.o.writeerr) {
|
||||
/*
|
||||
* Write error. Send a negative value to the callback,
|
||||
* and mark the thread as defunct (because the output
|
||||
* thread is terminating by now).
|
||||
*/
|
||||
h->u.o.defunct = true;
|
||||
h->u.o.sentdata(h, 0, h->u.o.writeerr);
|
||||
} else {
|
||||
bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten);
|
||||
noise_ultralight(NOISE_SOURCE_IOLEN, h->u.o.lenwritten);
|
||||
h->u.o.sentdata(h, bufchain_size(&h->u.o.queued_data), 0);
|
||||
handle_try_output(&h->u.o);
|
||||
}
|
||||
h->u.o.sentdata(h, bufchain_size(&h->u.o.queued_data), 0);
|
||||
handle_try_output(&h->u.o);
|
||||
}
|
||||
break;
|
||||
|
||||
case HT_FOREIGN:
|
||||
|
@ -51,11 +51,11 @@ static size_t handle_gotdata(
|
||||
HandleSocket *hs = (HandleSocket *)handle_get_privdata(h);
|
||||
|
||||
if (err) {
|
||||
plug_closing(hs->plug, "Read error from handle", 0, 0);
|
||||
return 0;
|
||||
plug_closing(hs->plug, "Read error from handle", 0, 0);
|
||||
return 0;
|
||||
} else if (len == 0) {
|
||||
plug_closing(hs->plug, NULL, 0, 0);
|
||||
return 0;
|
||||
plug_closing(hs->plug, NULL, 0, 0);
|
||||
return 0;
|
||||
} else {
|
||||
assert(hs->frozen != FROZEN && hs->frozen != THAWING);
|
||||
if (hs->frozen == FREEZING) {
|
||||
@ -75,7 +75,7 @@ static size_t handle_gotdata(
|
||||
return INT_MAX;
|
||||
} else {
|
||||
plug_receive(hs->plug, 0, data, len);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -108,7 +108,7 @@ static Plug *sk_handle_plug(Socket *s, Plug *p)
|
||||
HandleSocket *hs = container_of(s, HandleSocket, sock);
|
||||
Plug *ret = hs->plug;
|
||||
if (p)
|
||||
hs->plug = p;
|
||||
hs->plug = p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -738,7 +738,7 @@ bool set_explicit_app_user_model_id(void)
|
||||
{
|
||||
if (p_SetCurrentProcessExplicitAppUserModelID(L"SimonTatham.PuTTY") == S_OK)
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -73,62 +73,62 @@ char *get_username(void)
|
||||
char *user;
|
||||
bool got_username = false;
|
||||
DECL_WINDOWS_FUNCTION(static, BOOLEAN, GetUserNameExA,
|
||||
(EXTENDED_NAME_FORMAT, LPSTR, PULONG));
|
||||
(EXTENDED_NAME_FORMAT, LPSTR, PULONG));
|
||||
|
||||
{
|
||||
static bool tried_usernameex = false;
|
||||
if (!tried_usernameex) {
|
||||
/* Not available on Win9x, so load dynamically */
|
||||
HMODULE secur32 = load_system32_dll("secur32.dll");
|
||||
/* If MIT Kerberos is installed, the following call to
|
||||
GET_WINDOWS_FUNCTION makes Windows implicitly load
|
||||
sspicli.dll WITHOUT proper path sanitizing, so better
|
||||
load it properly before */
|
||||
HMODULE sspicli = load_system32_dll("sspicli.dll");
|
||||
static bool tried_usernameex = false;
|
||||
if (!tried_usernameex) {
|
||||
/* Not available on Win9x, so load dynamically */
|
||||
HMODULE secur32 = load_system32_dll("secur32.dll");
|
||||
/* If MIT Kerberos is installed, the following call to
|
||||
GET_WINDOWS_FUNCTION makes Windows implicitly load
|
||||
sspicli.dll WITHOUT proper path sanitizing, so better
|
||||
load it properly before */
|
||||
HMODULE sspicli = load_system32_dll("sspicli.dll");
|
||||
(void)sspicli; /* squash compiler warning about unused variable */
|
||||
GET_WINDOWS_FUNCTION(secur32, GetUserNameExA);
|
||||
tried_usernameex = true;
|
||||
}
|
||||
GET_WINDOWS_FUNCTION(secur32, GetUserNameExA);
|
||||
tried_usernameex = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_GetUserNameExA) {
|
||||
/*
|
||||
* If available, use the principal -- this avoids the problem
|
||||
* that the local username is case-insensitive but Kerberos
|
||||
* usernames are case-sensitive.
|
||||
*/
|
||||
/*
|
||||
* If available, use the principal -- this avoids the problem
|
||||
* that the local username is case-insensitive but Kerberos
|
||||
* usernames are case-sensitive.
|
||||
*/
|
||||
|
||||
/* Get the length */
|
||||
namelen = 0;
|
||||
(void) p_GetUserNameExA(NameUserPrincipal, NULL, &namelen);
|
||||
/* Get the length */
|
||||
namelen = 0;
|
||||
(void) p_GetUserNameExA(NameUserPrincipal, NULL, &namelen);
|
||||
|
||||
user = snewn(namelen, char);
|
||||
got_username = p_GetUserNameExA(NameUserPrincipal, user, &namelen);
|
||||
if (got_username) {
|
||||
char *p = strchr(user, '@');
|
||||
if (p) *p = 0;
|
||||
} else {
|
||||
sfree(user);
|
||||
}
|
||||
user = snewn(namelen, char);
|
||||
got_username = p_GetUserNameExA(NameUserPrincipal, user, &namelen);
|
||||
if (got_username) {
|
||||
char *p = strchr(user, '@');
|
||||
if (p) *p = 0;
|
||||
} else {
|
||||
sfree(user);
|
||||
}
|
||||
}
|
||||
|
||||
if (!got_username) {
|
||||
/* Fall back to local user name */
|
||||
namelen = 0;
|
||||
if (!GetUserName(NULL, &namelen)) {
|
||||
/*
|
||||
* Apparently this doesn't work at least on Windows XP SP2.
|
||||
* Thus assume a maximum of 256. It will fail again if it
|
||||
* doesn't fit.
|
||||
*/
|
||||
namelen = 256;
|
||||
}
|
||||
/* Fall back to local user name */
|
||||
namelen = 0;
|
||||
if (!GetUserName(NULL, &namelen)) {
|
||||
/*
|
||||
* Apparently this doesn't work at least on Windows XP SP2.
|
||||
* Thus assume a maximum of 256. It will fail again if it
|
||||
* doesn't fit.
|
||||
*/
|
||||
namelen = 256;
|
||||
}
|
||||
|
||||
user = snewn(namelen, char);
|
||||
got_username = GetUserName(user, &namelen);
|
||||
if (!got_username) {
|
||||
sfree(user);
|
||||
}
|
||||
user = snewn(namelen, char);
|
||||
got_username = GetUserName(user, &namelen);
|
||||
if (!got_username) {
|
||||
sfree(user);
|
||||
}
|
||||
}
|
||||
|
||||
return got_username ? user : NULL;
|
||||
@ -372,35 +372,35 @@ void escape_registry_key(const char *in, strbuf *out)
|
||||
static const char hex[16] = "0123456789ABCDEF";
|
||||
|
||||
while (*in) {
|
||||
if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
|
||||
*in == '%' || *in < ' ' || *in > '~' || (*in == '.'
|
||||
&& !candot)) {
|
||||
if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
|
||||
*in == '%' || *in < ' ' || *in > '~' || (*in == '.'
|
||||
&& !candot)) {
|
||||
put_byte(out, '%');
|
||||
put_byte(out, hex[((unsigned char) *in) >> 4]);
|
||||
put_byte(out, hex[((unsigned char) *in) & 15]);
|
||||
} else
|
||||
put_byte(out, *in);
|
||||
in++;
|
||||
candot = true;
|
||||
put_byte(out, hex[((unsigned char) *in) >> 4]);
|
||||
put_byte(out, hex[((unsigned char) *in) & 15]);
|
||||
} else
|
||||
put_byte(out, *in);
|
||||
in++;
|
||||
candot = true;
|
||||
}
|
||||
}
|
||||
|
||||
void unescape_registry_key(const char *in, strbuf *out)
|
||||
{
|
||||
while (*in) {
|
||||
if (*in == '%' && in[1] && in[2]) {
|
||||
int i, j;
|
||||
if (*in == '%' && in[1] && in[2]) {
|
||||
int i, j;
|
||||
|
||||
i = in[1] - '0';
|
||||
i -= (i > 9 ? 7 : 0);
|
||||
j = in[2] - '0';
|
||||
j -= (j > 9 ? 7 : 0);
|
||||
i = in[1] - '0';
|
||||
i -= (i > 9 ? 7 : 0);
|
||||
j = in[2] - '0';
|
||||
j -= (j > 9 ? 7 : 0);
|
||||
|
||||
put_byte(out, (i << 4) + j);
|
||||
in += 3;
|
||||
} else {
|
||||
put_byte(out, (i << 4) + j);
|
||||
in += 3;
|
||||
} else {
|
||||
put_byte(out, *in++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,17 +414,17 @@ void dputs(const char *buf)
|
||||
DWORD dw;
|
||||
|
||||
if (!debug_got_console) {
|
||||
if (AllocConsole()) {
|
||||
debug_got_console = 1;
|
||||
debug_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
if (AllocConsole()) {
|
||||
debug_got_console = 1;
|
||||
debug_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
}
|
||||
if (!debug_fp) {
|
||||
debug_fp = fopen("debug.log", "w");
|
||||
debug_fp = fopen("debug.log", "w");
|
||||
}
|
||||
|
||||
if (debug_hdl != INVALID_HANDLE_VALUE) {
|
||||
WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL);
|
||||
WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL);
|
||||
}
|
||||
fputs(buf, debug_fp);
|
||||
fflush(debug_fp);
|
||||
|
@ -25,15 +25,15 @@ void smemclr(void *b, size_t n) {
|
||||
|
||||
/*
|
||||
* Design:
|
||||
*
|
||||
*
|
||||
* We start by reserving as much virtual address space as Windows
|
||||
* will sensibly (or not sensibly) let us have. We flag it all as
|
||||
* invalid memory.
|
||||
*
|
||||
*
|
||||
* Any allocation attempt is satisfied by committing one or more
|
||||
* pages, with an uncommitted page on either side. The returned
|
||||
* memory region is jammed up against the _end_ of the pages.
|
||||
*
|
||||
*
|
||||
* Freeing anything causes instantaneous decommitment of the pages
|
||||
* involved, so stale pointers are caught as soon as possible.
|
||||
*/
|
||||
@ -59,10 +59,10 @@ static void minefield_init(void)
|
||||
int i;
|
||||
|
||||
for (size = 0x40000000; size > 0; size = ((size >> 3) * 7) & ~0xFFF) {
|
||||
minefield_region = VirtualAlloc(NULL, size,
|
||||
MEM_RESERVE, PAGE_NOACCESS);
|
||||
if (minefield_region)
|
||||
break;
|
||||
minefield_region = VirtualAlloc(NULL, size,
|
||||
MEM_RESERVE, PAGE_NOACCESS);
|
||||
if (minefield_region)
|
||||
break;
|
||||
}
|
||||
minefield_size = size;
|
||||
|
||||
@ -80,13 +80,13 @@ static void minefield_init(void)
|
||||
* Commit the admin region.
|
||||
*/
|
||||
VirtualAlloc(minefield_admin, minefield_npages * 2,
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
/*
|
||||
* Mark all pages as unused (0xFFFF).
|
||||
*/
|
||||
for (i = 0; i < minefield_npages; i++)
|
||||
minefield_admin[i] = 0xFFFF;
|
||||
minefield_admin[i] = 0xFFFF;
|
||||
|
||||
/*
|
||||
* Hide the admin region.
|
||||
@ -119,27 +119,27 @@ static void *minefield_alloc(int size)
|
||||
pos = minefield_curpos;
|
||||
lim = minefield_npages;
|
||||
while (1) {
|
||||
/* Skip over used pages. */
|
||||
while (pos < lim && minefield_admin[pos] != 0xFFFF)
|
||||
pos++;
|
||||
/* Count unused pages. */
|
||||
start = pos;
|
||||
while (pos < lim && pos - start < npages + 2 &&
|
||||
minefield_admin[pos] == 0xFFFF)
|
||||
pos++;
|
||||
if (pos - start == npages + 2)
|
||||
break;
|
||||
/* If we've reached the limit, reset the limit or stop. */
|
||||
if (pos >= lim) {
|
||||
if (lim == minefield_npages) {
|
||||
/* go round and start again at zero */
|
||||
lim = minefield_curpos;
|
||||
pos = 0;
|
||||
} else {
|
||||
minefield_admin_hide(1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* Skip over used pages. */
|
||||
while (pos < lim && minefield_admin[pos] != 0xFFFF)
|
||||
pos++;
|
||||
/* Count unused pages. */
|
||||
start = pos;
|
||||
while (pos < lim && pos - start < npages + 2 &&
|
||||
minefield_admin[pos] == 0xFFFF)
|
||||
pos++;
|
||||
if (pos - start == npages + 2)
|
||||
break;
|
||||
/* If we've reached the limit, reset the limit or stop. */
|
||||
if (pos >= lim) {
|
||||
if (lim == minefield_npages) {
|
||||
/* go round and start again at zero */
|
||||
lim = minefield_curpos;
|
||||
pos = 0;
|
||||
} else {
|
||||
minefield_admin_hide(1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minefield_curpos = pos - 1;
|
||||
@ -156,13 +156,13 @@ static void *minefield_alloc(int size)
|
||||
* Update the admin region.
|
||||
*/
|
||||
for (i = start + 2; i < start + npages + 1; i++)
|
||||
minefield_admin[i] = 0xFFFE; /* used but no region starts here */
|
||||
minefield_admin[i] = 0xFFFE; /* used but no region starts here */
|
||||
minefield_admin[start + 1] = region_start % PAGESIZE;
|
||||
|
||||
minefield_admin_hide(1);
|
||||
|
||||
VirtualAlloc((char *) minefield_pages + region_start, size,
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
return (char *) minefield_pages + region_start;
|
||||
}
|
||||
|
||||
@ -175,10 +175,10 @@ static void minefield_free(void *ptr)
|
||||
region_start = (char *) ptr - (char *) minefield_pages;
|
||||
i = region_start / PAGESIZE;
|
||||
if (i < 0 || i >= minefield_npages ||
|
||||
minefield_admin[i] != region_start % PAGESIZE)
|
||||
minefield_bomb();
|
||||
minefield_admin[i] != region_start % PAGESIZE)
|
||||
minefield_bomb();
|
||||
for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) {
|
||||
minefield_admin[j] = 0xFFFF;
|
||||
minefield_admin[j] = 0xFFFF;
|
||||
}
|
||||
|
||||
VirtualFree(ptr, j * PAGESIZE - region_start, MEM_DECOMMIT);
|
||||
@ -195,8 +195,8 @@ static int minefield_get_size(void *ptr)
|
||||
region_start = (char *) ptr - (char *) minefield_pages;
|
||||
i = region_start / PAGESIZE;
|
||||
if (i < 0 || i >= minefield_npages ||
|
||||
minefield_admin[i] != region_start % PAGESIZE)
|
||||
minefield_bomb();
|
||||
minefield_admin[i] != region_start % PAGESIZE)
|
||||
minefield_bomb();
|
||||
for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++);
|
||||
|
||||
minefield_admin_hide(1);
|
||||
@ -207,14 +207,14 @@ static int minefield_get_size(void *ptr)
|
||||
void *minefield_c_malloc(size_t size)
|
||||
{
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
minefield_init();
|
||||
return minefield_alloc(size);
|
||||
}
|
||||
|
||||
void minefield_c_free(void *p)
|
||||
{
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
minefield_init();
|
||||
minefield_free(p);
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ void *minefield_c_realloc(void *p, size_t size)
|
||||
size_t oldsize;
|
||||
void *q;
|
||||
if (!minefield_initialised)
|
||||
minefield_init();
|
||||
minefield_init();
|
||||
q = minefield_alloc(size);
|
||||
oldsize = minefield_get_size(p);
|
||||
memcpy(q, p, (oldsize < size ? oldsize : size));
|
||||
@ -235,7 +235,7 @@ void *minefield_c_realloc(void *p, size_t size)
|
||||
return q;
|
||||
}
|
||||
|
||||
#endif /* MINEFIELD */
|
||||
#endif /* MINEFIELD */
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER < 1800
|
||||
|
||||
|
1196
windows/winnet.c
1196
windows/winnet.c
File diff suppressed because it is too large
Load Diff
@ -58,10 +58,10 @@ void noise_get_heavy(void (*func) (void *, int))
|
||||
strcat(winpath, "\\*");
|
||||
srch = FindFirstFile(winpath, &finddata);
|
||||
if (srch != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
func(&finddata, sizeof(finddata));
|
||||
} while (FindNextFile(srch, &finddata));
|
||||
FindClose(srch);
|
||||
do {
|
||||
func(&finddata, sizeof(finddata));
|
||||
} while (FindNextFile(srch, &finddata));
|
||||
FindClose(srch);
|
||||
}
|
||||
|
||||
pid = GetCurrentProcessId();
|
||||
@ -105,10 +105,10 @@ void noise_regular(void)
|
||||
random_add_noise(NOISE_SOURCE_MEMINFO, &memstat, sizeof(memstat));
|
||||
|
||||
GetThreadTimes(GetCurrentThread(), times, times + 1, times + 2,
|
||||
times + 3);
|
||||
times + 3);
|
||||
random_add_noise(NOISE_SOURCE_THREADTIME, ×, sizeof(times));
|
||||
GetProcessTimes(GetCurrentProcess(), times, times + 1, times + 2,
|
||||
times + 3);
|
||||
times + 3);
|
||||
random_add_noise(NOISE_SOURCE_PROCTIME, ×, sizeof(times));
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ void noise_ultralight(NoiseSourceId id, unsigned long data)
|
||||
random_add_noise(NOISE_SOURCE_TIME, &wintime, sizeof(DWORD));
|
||||
|
||||
if (QueryPerformanceCounter(&perftime))
|
||||
random_add_noise(NOISE_SOURCE_PERFCOUNT, &perftime, sizeof(perftime));
|
||||
random_add_noise(NOISE_SOURCE_PERFCOUNT, &perftime, sizeof(perftime));
|
||||
}
|
||||
|
||||
uint64_t prng_reseed_time_ms(void)
|
||||
|
@ -38,7 +38,7 @@ static Plug *sk_namedpipeserver_plug(Socket *s, Plug *p)
|
||||
NamedPipeServerSocket *ps = container_of(s, NamedPipeServerSocket, sock);
|
||||
Plug *ret = ps->plug;
|
||||
if (p)
|
||||
ps->plug = p;
|
||||
ps->plug = p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
1530
windows/winpgen.c
1530
windows/winpgen.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -20,9 +20,9 @@ bool agent_exists(void)
|
||||
HWND hwnd;
|
||||
hwnd = FindWindow("Pageant", "Pageant");
|
||||
if (!hwnd)
|
||||
return false;
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void agent_cancel_query(agent_pending_query *q)
|
||||
@ -52,7 +52,7 @@ agent_pending_query *agent_query(
|
||||
|
||||
hwnd = FindWindow("Pageant", "Pageant");
|
||||
if (!hwnd)
|
||||
return NULL; /* *out == NULL, so failure */
|
||||
return NULL; /* *out == NULL, so failure */
|
||||
mapname = dupprintf("PageantRequest%08x", (unsigned)GetCurrentThreadId());
|
||||
|
||||
psa = NULL;
|
||||
@ -90,10 +90,10 @@ agent_pending_query *agent_query(
|
||||
#endif /* NO_SECURITY */
|
||||
|
||||
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, psa, PAGE_READWRITE,
|
||||
0, AGENT_MAX_MSGLEN, mapname);
|
||||
0, AGENT_MAX_MSGLEN, mapname);
|
||||
if (filemap == NULL || filemap == INVALID_HANDLE_VALUE) {
|
||||
sfree(mapname);
|
||||
return NULL; /* *out == NULL, so failure */
|
||||
return NULL; /* *out == NULL, so failure */
|
||||
}
|
||||
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
|
||||
strbuf_finalise_agent_query(query);
|
||||
@ -113,7 +113,7 @@ agent_pending_query *agent_query(
|
||||
if (length_field > 0 && length_field <= AGENT_MAX_MSGLEN - 4) {
|
||||
retlen = length_field + 4;
|
||||
ret = snewn(retlen, unsigned char);
|
||||
memcpy(ret, p, retlen);
|
||||
memcpy(ret, p, retlen);
|
||||
*out = ret;
|
||||
*outlen = retlen;
|
||||
} else {
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
|
||||
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
|
||||
#include "putty.h"
|
||||
#include "storage.h"
|
||||
#include "tree234.h"
|
||||
@ -50,13 +50,13 @@ static void plink_echoedit_update(Seat *seat, bool echo, bool edit)
|
||||
|
||||
mode = ENABLE_PROCESSED_INPUT;
|
||||
if (echo)
|
||||
mode = mode | ENABLE_ECHO_INPUT;
|
||||
mode = mode | ENABLE_ECHO_INPUT;
|
||||
else
|
||||
mode = mode & ~ENABLE_ECHO_INPUT;
|
||||
mode = mode & ~ENABLE_ECHO_INPUT;
|
||||
if (edit)
|
||||
mode = mode | ENABLE_LINE_INPUT;
|
||||
mode = mode | ENABLE_LINE_INPUT;
|
||||
else
|
||||
mode = mode & ~ENABLE_LINE_INPUT;
|
||||
mode = mode & ~ENABLE_LINE_INPUT;
|
||||
SetConsoleMode(inhandle, mode);
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ static int plink_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input)
|
||||
int ret;
|
||||
ret = cmdline_get_passwd_input(p);
|
||||
if (ret == -1)
|
||||
ret = console_get_userpass_input(p);
|
||||
ret = console_get_userpass_input(p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ static Seat plink_seat[1] = {{ &plink_seat_vt }};
|
||||
static DWORD main_thread_id;
|
||||
|
||||
void agent_schedule_callback(void (*callback)(void *, void *, int),
|
||||
void *callback_ctx, void *data, int len)
|
||||
void *callback_ctx, void *data, int len)
|
||||
{
|
||||
struct agent_callback *c = snew(struct agent_callback);
|
||||
c->callback = callback;
|
||||
@ -194,18 +194,18 @@ char *do_select(SOCKET skt, bool startup)
|
||||
{
|
||||
int events;
|
||||
if (startup) {
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
} else {
|
||||
events = 0;
|
||||
events = 0;
|
||||
}
|
||||
if (p_WSAEventSelect(skt, netevent, events) == SOCKET_ERROR) {
|
||||
switch (p_WSAGetLastError()) {
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
default:
|
||||
return "WSAEventSelect(): unknown error";
|
||||
}
|
||||
switch (p_WSAGetLastError()) {
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
default:
|
||||
return "WSAEventSelect(): unknown error";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -213,40 +213,40 @@ char *do_select(SOCKET skt, bool startup)
|
||||
size_t stdin_gotdata(struct handle *h, const void *data, size_t len, int err)
|
||||
{
|
||||
if (err) {
|
||||
char buf[4096];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
|
||||
buf, lenof(buf), NULL);
|
||||
buf[lenof(buf)-1] = '\0';
|
||||
if (buf[strlen(buf)-1] == '\n')
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
fprintf(stderr, "Unable to read from standard input: %s\n", buf);
|
||||
cleanup_exit(0);
|
||||
char buf[4096];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
|
||||
buf, lenof(buf), NULL);
|
||||
buf[lenof(buf)-1] = '\0';
|
||||
if (buf[strlen(buf)-1] == '\n')
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
fprintf(stderr, "Unable to read from standard input: %s\n", buf);
|
||||
cleanup_exit(0);
|
||||
}
|
||||
|
||||
noise_ultralight(NOISE_SOURCE_IOLEN, len);
|
||||
if (backend_connected(backend)) {
|
||||
if (len > 0) {
|
||||
if (len > 0) {
|
||||
return backend_send(backend, data, len);
|
||||
} else {
|
||||
} else {
|
||||
backend_special(backend, SS_EOF, 0);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stdouterr_sent(struct handle *h, size_t new_backlog, int err)
|
||||
{
|
||||
if (err) {
|
||||
char buf[4096];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
|
||||
buf, lenof(buf), NULL);
|
||||
buf[lenof(buf)-1] = '\0';
|
||||
if (buf[strlen(buf)-1] == '\n')
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
fprintf(stderr, "Unable to write to standard %s: %s\n",
|
||||
(h == stdout_handle ? "output" : "error"), buf);
|
||||
cleanup_exit(0);
|
||||
char buf[4096];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0,
|
||||
buf, lenof(buf), NULL);
|
||||
buf[lenof(buf)-1] = '\0';
|
||||
if (buf[strlen(buf)-1] == '\n')
|
||||
buf[strlen(buf)-1] = '\0';
|
||||
fprintf(stderr, "Unable to write to standard %s: %s\n",
|
||||
(h == stdout_handle ? "output" : "error"), buf);
|
||||
cleanup_exit(0);
|
||||
}
|
||||
|
||||
if (backend_connected(backend)) {
|
||||
@ -299,22 +299,22 @@ int main(int argc, char **argv)
|
||||
default_port = conf_get_int(conf, CONF_port);
|
||||
errors = false;
|
||||
{
|
||||
/*
|
||||
* Override the default protocol if PLINK_PROTOCOL is set.
|
||||
*/
|
||||
char *p = getenv("PLINK_PROTOCOL");
|
||||
if (p) {
|
||||
/*
|
||||
* Override the default protocol if PLINK_PROTOCOL is set.
|
||||
*/
|
||||
char *p = getenv("PLINK_PROTOCOL");
|
||||
if (p) {
|
||||
const struct BackendVtable *vt = backend_vt_from_name(p);
|
||||
if (vt) {
|
||||
default_protocol = vt->protocol;
|
||||
default_port = vt->default_port;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
conf_set_int(conf, CONF_port, default_port);
|
||||
}
|
||||
}
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
conf_set_int(conf, CONF_port, default_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (--argc) {
|
||||
char *p = *++argv;
|
||||
char *p = *++argv;
|
||||
int ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL),
|
||||
1, conf);
|
||||
if (ret == -2) {
|
||||
@ -353,7 +353,7 @@ int main(int argc, char **argv)
|
||||
sanitise_stderr = FORCE_OFF;
|
||||
} else if (!strcmp(p, "-no-antispoof")) {
|
||||
console_antispoof_prompt = false;
|
||||
} else if (*p != '-') {
|
||||
} else if (*p != '-') {
|
||||
strbuf *cmdbuf = strbuf_new();
|
||||
|
||||
while (argc > 0) {
|
||||
@ -369,7 +369,7 @@ int main(int argc, char **argv)
|
||||
conf_set_bool(conf, CONF_nopty, true); /* command => no tty */
|
||||
|
||||
strbuf_free(cmdbuf);
|
||||
break; /* done with cmdline */
|
||||
break; /* done with cmdline */
|
||||
} else {
|
||||
fprintf(stderr, "plink: unknown option \"%s\"\n", p);
|
||||
errors = true;
|
||||
@ -377,10 +377,10 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (errors)
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
if (!cmdline_host_ok(conf)) {
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
prepare_session(conf);
|
||||
@ -397,9 +397,9 @@ int main(int argc, char **argv)
|
||||
conf_set_bool(conf, CONF_ssh_subsys, true);
|
||||
|
||||
if (!*conf_get_str(conf, CONF_remote_cmd) &&
|
||||
!*conf_get_str(conf, CONF_remote_cmd2) &&
|
||||
!*conf_get_str(conf, CONF_ssh_nc_host))
|
||||
flags |= FLAG_INTERACTIVE;
|
||||
!*conf_get_str(conf, CONF_remote_cmd2) &&
|
||||
!*conf_get_str(conf, CONF_ssh_nc_host))
|
||||
flags |= FLAG_INTERACTIVE;
|
||||
|
||||
/*
|
||||
* Select protocol. This is farmed out into a table in a
|
||||
@ -407,15 +407,15 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
|
||||
if (vt == NULL) {
|
||||
fprintf(stderr,
|
||||
"Internal fault: Unsupported protocol found\n");
|
||||
return 1;
|
||||
fprintf(stderr,
|
||||
"Internal fault: Unsupported protocol found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sk_init();
|
||||
if (p_WSAEventSelect == NULL) {
|
||||
fprintf(stderr, "Plink requires WinSock 2\n");
|
||||
return 1;
|
||||
fprintf(stderr, "Plink requires WinSock 2\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -424,10 +424,10 @@ int main(int argc, char **argv)
|
||||
* the "simple" flag.
|
||||
*/
|
||||
if (conf_get_int(conf, CONF_protocol) == PROT_SSH &&
|
||||
!conf_get_bool(conf, CONF_x11_forward) &&
|
||||
!conf_get_bool(conf, CONF_agentfwd) &&
|
||||
!conf_get_str_nthstrkey(conf, CONF_portfwd, 0))
|
||||
conf_set_bool(conf, CONF_ssh_simple, true);
|
||||
!conf_get_bool(conf, CONF_x11_forward) &&
|
||||
!conf_get_bool(conf, CONF_agentfwd) &&
|
||||
!conf_get_str_nthstrkey(conf, CONF_portfwd, 0))
|
||||
conf_set_bool(conf, CONF_ssh_simple, true);
|
||||
|
||||
logctx = log_init(default_logpolicy, conf);
|
||||
|
||||
@ -453,22 +453,22 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
netevent = CreateEvent(NULL, false, false, NULL);
|
||||
{
|
||||
const char *error;
|
||||
char *realhost;
|
||||
/* nodelay is only useful if stdin is a character device (console) */
|
||||
bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) &&
|
||||
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
|
||||
const char *error;
|
||||
char *realhost;
|
||||
/* nodelay is only useful if stdin is a character device (console) */
|
||||
bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) &&
|
||||
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
|
||||
|
||||
error = backend_init(vt, plink_seat, &backend, logctx, conf,
|
||||
conf_get_str(conf, CONF_host),
|
||||
conf_get_int(conf, CONF_port),
|
||||
&realhost, nodelay,
|
||||
conf_get_bool(conf, CONF_tcp_keepalives));
|
||||
if (error) {
|
||||
fprintf(stderr, "Unable to open connection:\n%s", error);
|
||||
return 1;
|
||||
}
|
||||
sfree(realhost);
|
||||
if (error) {
|
||||
fprintf(stderr, "Unable to open connection:\n%s", error);
|
||||
return 1;
|
||||
}
|
||||
sfree(realhost);
|
||||
}
|
||||
|
||||
inhandle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
@ -529,74 +529,74 @@ int main(int argc, char **argv)
|
||||
now = GETTICKCOUNT();
|
||||
|
||||
while (1) {
|
||||
int nhandles;
|
||||
HANDLE *handles;
|
||||
int n;
|
||||
DWORD ticks;
|
||||
int nhandles;
|
||||
HANDLE *handles;
|
||||
int n;
|
||||
DWORD ticks;
|
||||
|
||||
if (!sending && backend_sendok(backend)) {
|
||||
stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL,
|
||||
0);
|
||||
sending = true;
|
||||
}
|
||||
stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL,
|
||||
0);
|
||||
sending = true;
|
||||
}
|
||||
|
||||
if (toplevel_callback_pending()) {
|
||||
ticks = 0;
|
||||
next = now;
|
||||
} else if (run_timers(now, &next)) {
|
||||
then = now;
|
||||
now = GETTICKCOUNT();
|
||||
if (now - then > next - then)
|
||||
ticks = 0;
|
||||
else
|
||||
ticks = next - now;
|
||||
} else {
|
||||
ticks = INFINITE;
|
||||
then = now;
|
||||
now = GETTICKCOUNT();
|
||||
if (now - then > next - then)
|
||||
ticks = 0;
|
||||
else
|
||||
ticks = next - now;
|
||||
} else {
|
||||
ticks = INFINITE;
|
||||
/* no need to initialise next here because we can never
|
||||
* get WAIT_TIMEOUT */
|
||||
}
|
||||
}
|
||||
|
||||
handles = handle_get_events(&nhandles);
|
||||
handles = sresize(handles, nhandles+1, HANDLE);
|
||||
handles[nhandles] = netevent;
|
||||
n = MsgWaitForMultipleObjects(nhandles+1, handles, false, ticks,
|
||||
QS_POSTMESSAGE);
|
||||
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
|
||||
handle_got_event(handles[n - WAIT_OBJECT_0]);
|
||||
} else if (n == WAIT_OBJECT_0 + nhandles) {
|
||||
WSANETWORKEVENTS things;
|
||||
SOCKET socket;
|
||||
int i, socketstate;
|
||||
handles = handle_get_events(&nhandles);
|
||||
handles = sresize(handles, nhandles+1, HANDLE);
|
||||
handles[nhandles] = netevent;
|
||||
n = MsgWaitForMultipleObjects(nhandles+1, handles, false, ticks,
|
||||
QS_POSTMESSAGE);
|
||||
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
|
||||
handle_got_event(handles[n - WAIT_OBJECT_0]);
|
||||
} else if (n == WAIT_OBJECT_0 + nhandles) {
|
||||
WSANETWORKEVENTS things;
|
||||
SOCKET socket;
|
||||
int i, socketstate;
|
||||
|
||||
/*
|
||||
* We must not call select_result() for any socket
|
||||
* until we have finished enumerating within the tree.
|
||||
* This is because select_result() may close the socket
|
||||
* and modify the tree.
|
||||
*/
|
||||
/* Count the active sockets. */
|
||||
i = 0;
|
||||
for (socket = first_socket(&socketstate);
|
||||
socket != INVALID_SOCKET;
|
||||
socket = next_socket(&socketstate)) i++;
|
||||
/*
|
||||
* We must not call select_result() for any socket
|
||||
* until we have finished enumerating within the tree.
|
||||
* This is because select_result() may close the socket
|
||||
* and modify the tree.
|
||||
*/
|
||||
/* Count the active sockets. */
|
||||
i = 0;
|
||||
for (socket = first_socket(&socketstate);
|
||||
socket != INVALID_SOCKET;
|
||||
socket = next_socket(&socketstate)) i++;
|
||||
|
||||
/* Expand the buffer if necessary. */
|
||||
/* Expand the buffer if necessary. */
|
||||
sgrowarray(sklist, sksize, i);
|
||||
|
||||
/* Retrieve the sockets into sklist. */
|
||||
skcount = 0;
|
||||
for (socket = first_socket(&socketstate);
|
||||
socket != INVALID_SOCKET;
|
||||
socket = next_socket(&socketstate)) {
|
||||
sklist[skcount++] = socket;
|
||||
}
|
||||
/* Retrieve the sockets into sklist. */
|
||||
skcount = 0;
|
||||
for (socket = first_socket(&socketstate);
|
||||
socket != INVALID_SOCKET;
|
||||
socket = next_socket(&socketstate)) {
|
||||
sklist[skcount++] = socket;
|
||||
}
|
||||
|
||||
/* Now we're done enumerating; go through the list. */
|
||||
for (i = 0; i < skcount; i++) {
|
||||
WPARAM wp;
|
||||
socket = sklist[i];
|
||||
wp = (WPARAM) socket;
|
||||
if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) {
|
||||
/* Now we're done enumerating; go through the list. */
|
||||
for (i = 0; i < skcount; i++) {
|
||||
WPARAM wp;
|
||||
socket = sklist[i];
|
||||
wp = (WPARAM) socket;
|
||||
if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) {
|
||||
static const struct { int bit, mask; } eventtypes[] = {
|
||||
{FD_CONNECT_BIT, FD_CONNECT},
|
||||
{FD_READ_BIT, FD_READ},
|
||||
@ -607,7 +607,7 @@ int main(int argc, char **argv)
|
||||
};
|
||||
int e;
|
||||
|
||||
noise_ultralight(NOISE_SOURCE_IOID, socket);
|
||||
noise_ultralight(NOISE_SOURCE_IOID, socket);
|
||||
|
||||
for (e = 0; e < lenof(eventtypes); e++)
|
||||
if (things.lNetworkEvents & eventtypes[e].mask) {
|
||||
@ -616,41 +616,41 @@ int main(int argc, char **argv)
|
||||
lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err);
|
||||
select_result(wp, lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (n == WAIT_OBJECT_0 + nhandles + 1) {
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, INVALID_HANDLE_VALUE,
|
||||
WM_AGENT_CALLBACK, WM_AGENT_CALLBACK,
|
||||
PM_REMOVE)) {
|
||||
struct agent_callback *c = (struct agent_callback *)msg.lParam;
|
||||
c->callback(c->callback_ctx, c->data, c->len);
|
||||
sfree(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (n == WAIT_OBJECT_0 + nhandles + 1) {
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, INVALID_HANDLE_VALUE,
|
||||
WM_AGENT_CALLBACK, WM_AGENT_CALLBACK,
|
||||
PM_REMOVE)) {
|
||||
struct agent_callback *c = (struct agent_callback *)msg.lParam;
|
||||
c->callback(c->callback_ctx, c->data, c->len);
|
||||
sfree(c);
|
||||
}
|
||||
}
|
||||
|
||||
run_toplevel_callbacks();
|
||||
|
||||
if (n == WAIT_TIMEOUT) {
|
||||
now = next;
|
||||
} else {
|
||||
now = GETTICKCOUNT();
|
||||
}
|
||||
if (n == WAIT_TIMEOUT) {
|
||||
now = next;
|
||||
} else {
|
||||
now = GETTICKCOUNT();
|
||||
}
|
||||
|
||||
sfree(handles);
|
||||
sfree(handles);
|
||||
|
||||
if (sending)
|
||||
if (sending)
|
||||
handle_unthrottle(stdin_handle, backend_sendbuffer(backend));
|
||||
|
||||
if (!backend_connected(backend) &&
|
||||
handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0)
|
||||
break; /* we closed the connection */
|
||||
handle_backlog(stdout_handle) + handle_backlog(stderr_handle) == 0)
|
||||
break; /* we closed the connection */
|
||||
}
|
||||
exitcode = backend_exitcode(backend);
|
||||
if (exitcode < 0) {
|
||||
fprintf(stderr, "Remote process exit code unavailable\n");
|
||||
exitcode = 1; /* this is an error condition */
|
||||
fprintf(stderr, "Remote process exit code unavailable\n");
|
||||
exitcode = 1; /* this is an error condition */
|
||||
}
|
||||
cleanup_exit(exitcode);
|
||||
return 0; /* placate compiler warning */
|
||||
return 0; /* placate compiler warning */
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ struct printer_enum_tag {
|
||||
int nprinters;
|
||||
DWORD enum_level;
|
||||
union {
|
||||
LPPRINTER_INFO_4 i4;
|
||||
LPPRINTER_INFO_5 i5;
|
||||
LPPRINTER_INFO_4 i4;
|
||||
LPPRINTER_INFO_5 i5;
|
||||
} info;
|
||||
};
|
||||
|
||||
@ -92,7 +92,7 @@ printer_enum *printer_start_enum(int *nprinters_ptr)
|
||||
printer_enum *ret = snew(printer_enum);
|
||||
char *buffer = NULL;
|
||||
|
||||
*nprinters_ptr = 0; /* default return value */
|
||||
*nprinters_ptr = 0; /* default return value */
|
||||
buffer = snewn(512, char);
|
||||
|
||||
/*
|
||||
@ -106,9 +106,9 @@ printer_enum *printer_start_enum(int *nprinters_ptr)
|
||||
* Bletch.
|
||||
*/
|
||||
if (osPlatformId != VER_PLATFORM_WIN32_NT) {
|
||||
ret->enum_level = 5;
|
||||
ret->enum_level = 5;
|
||||
} else {
|
||||
ret->enum_level = 4;
|
||||
ret->enum_level = 4;
|
||||
}
|
||||
|
||||
if (!printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
|
||||
@ -117,14 +117,14 @@ printer_enum *printer_start_enum(int *nprinters_ptr)
|
||||
|
||||
switch (ret->enum_level) {
|
||||
case 4:
|
||||
ret->info.i4 = (LPPRINTER_INFO_4)buffer;
|
||||
break;
|
||||
ret->info.i4 = (LPPRINTER_INFO_4)buffer;
|
||||
break;
|
||||
case 5:
|
||||
ret->info.i5 = (LPPRINTER_INFO_5)buffer;
|
||||
break;
|
||||
ret->info.i5 = (LPPRINTER_INFO_5)buffer;
|
||||
break;
|
||||
}
|
||||
ret->nprinters = *nprinters_ptr;
|
||||
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
@ -137,30 +137,30 @@ printer_enum *printer_start_enum(int *nprinters_ptr)
|
||||
char *printer_get_name(printer_enum *pe, int i)
|
||||
{
|
||||
if (!pe)
|
||||
return NULL;
|
||||
return NULL;
|
||||
if (i < 0 || i >= pe->nprinters)
|
||||
return NULL;
|
||||
return NULL;
|
||||
switch (pe->enum_level) {
|
||||
case 4:
|
||||
return pe->info.i4[i].pPrinterName;
|
||||
return pe->info.i4[i].pPrinterName;
|
||||
case 5:
|
||||
return pe->info.i5[i].pPrinterName;
|
||||
return pe->info.i5[i].pPrinterName;
|
||||
default:
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void printer_finish_enum(printer_enum *pe)
|
||||
{
|
||||
if (!pe)
|
||||
return;
|
||||
return;
|
||||
switch (pe->enum_level) {
|
||||
case 4:
|
||||
sfree(pe->info.i4);
|
||||
break;
|
||||
sfree(pe->info.i4);
|
||||
break;
|
||||
case 5:
|
||||
sfree(pe->info.i5);
|
||||
break;
|
||||
sfree(pe->info.i5);
|
||||
break;
|
||||
}
|
||||
sfree(pe);
|
||||
}
|
||||
@ -175,29 +175,29 @@ printer_job *printer_start_job(char *printer)
|
||||
|
||||
ret->hprinter = NULL;
|
||||
if (!p_OpenPrinter(printer, &ret->hprinter, NULL))
|
||||
goto error;
|
||||
goto error;
|
||||
|
||||
docinfo.pDocName = "PuTTY remote printer output";
|
||||
docinfo.pOutputFile = NULL;
|
||||
docinfo.pDatatype = "RAW";
|
||||
|
||||
if (!p_StartDocPrinter(ret->hprinter, 1, (LPBYTE)&docinfo))
|
||||
goto error;
|
||||
goto error;
|
||||
jobstarted = true;
|
||||
|
||||
if (!p_StartPagePrinter(ret->hprinter))
|
||||
goto error;
|
||||
goto error;
|
||||
pagestarted = true;
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
if (pagestarted)
|
||||
p_EndPagePrinter(ret->hprinter);
|
||||
p_EndPagePrinter(ret->hprinter);
|
||||
if (jobstarted)
|
||||
p_EndDocPrinter(ret->hprinter);
|
||||
p_EndDocPrinter(ret->hprinter);
|
||||
if (ret->hprinter)
|
||||
p_ClosePrinter(ret->hprinter);
|
||||
p_ClosePrinter(ret->hprinter);
|
||||
sfree(ret);
|
||||
return NULL;
|
||||
}
|
||||
@ -207,7 +207,7 @@ void printer_job_data(printer_job *pj, const void *data, size_t len)
|
||||
DWORD written;
|
||||
|
||||
if (!pj)
|
||||
return;
|
||||
return;
|
||||
|
||||
p_WritePrinter(pj->hprinter, (void *)data, len, &written);
|
||||
}
|
||||
@ -215,7 +215,7 @@ void printer_job_data(printer_job *pj, const void *data, size_t len)
|
||||
void printer_finish_job(printer_job *pj)
|
||||
{
|
||||
if (!pj)
|
||||
return;
|
||||
return;
|
||||
|
||||
p_EndPagePrinter(pj->hprinter);
|
||||
p_EndDocPrinter(pj->hprinter);
|
||||
|
@ -26,7 +26,7 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
cmd = format_telnet_command(addr, port, conf);
|
||||
|
||||
@ -34,9 +34,9 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
|
||||
sk_addr_free(addr);
|
||||
|
||||
{
|
||||
char *msg = dupprintf("Starting local proxy command: %s", cmd);
|
||||
plug_log(plug, 2, NULL, 0, msg, 0);
|
||||
sfree(msg);
|
||||
char *msg = dupprintf("Starting local proxy command: %s", cmd);
|
||||
plug_log(plug, 2, NULL, 0, msg, 0);
|
||||
sfree(msg);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -48,16 +48,16 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
|
||||
sa.bInheritHandle = true;
|
||||
if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) {
|
||||
sfree(cmd);
|
||||
return new_error_socket_fmt(
|
||||
return new_error_socket_fmt(
|
||||
plug, "Unable to create pipes for proxy command: %s",
|
||||
win_strerror(GetLastError()));
|
||||
}
|
||||
|
||||
if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) {
|
||||
sfree(cmd);
|
||||
CloseHandle(us_from_cmd);
|
||||
CloseHandle(cmd_to_us);
|
||||
return new_error_socket_fmt(
|
||||
CloseHandle(us_from_cmd);
|
||||
CloseHandle(cmd_to_us);
|
||||
return new_error_socket_fmt(
|
||||
plug, "Unable to create pipes for proxy command: %s",
|
||||
win_strerror(GetLastError()));
|
||||
}
|
||||
@ -89,8 +89,8 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
|
||||
si.hStdOutput = cmd_to_us;
|
||||
si.hStdError = cmd_err_to_us;
|
||||
CreateProcess(NULL, cmd, NULL, NULL, true,
|
||||
CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
|
||||
NULL, NULL, &si, &pi);
|
||||
CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
|
||||
NULL, NULL, &si, &pi);
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
|
@ -140,7 +140,7 @@ bool getsids(char **error)
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool make_private_security_descriptor(DWORD permissions,
|
||||
PSECURITY_DESCRIPTOR *psd,
|
||||
@ -236,14 +236,14 @@ static bool really_restrict_process_acl(char **error)
|
||||
PACL acl = NULL;
|
||||
|
||||
static const DWORD nastyace=WRITE_DAC | WRITE_OWNER |
|
||||
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
|
||||
PROCESS_DUP_HANDLE |
|
||||
PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION |
|
||||
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE |
|
||||
PROCESS_SUSPEND_RESUME;
|
||||
PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
|
||||
PROCESS_DUP_HANDLE |
|
||||
PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION |
|
||||
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE |
|
||||
PROCESS_SUSPEND_RESUME;
|
||||
|
||||
if (!getsids(error))
|
||||
goto cleanup;
|
||||
goto cleanup;
|
||||
|
||||
memset(ea, 0, sizeof(ea));
|
||||
|
||||
@ -264,7 +264,7 @@ static bool really_restrict_process_acl(char **error)
|
||||
acl_err = p_SetEntriesInAclA(2, ea, NULL, &acl);
|
||||
|
||||
if (acl_err != ERROR_SUCCESS || acl == NULL) {
|
||||
*error = dupprintf("unable to construct ACL: %s",
|
||||
*error = dupprintf("unable to construct ACL: %s",
|
||||
win_strerror(acl_err));
|
||||
goto cleanup;
|
||||
}
|
||||
@ -273,14 +273,14 @@ static bool really_restrict_process_acl(char **error)
|
||||
(GetCurrentProcess(), SE_KERNEL_OBJECT,
|
||||
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
|
||||
usersid, NULL, acl, NULL)) {
|
||||
*error = dupprintf("Unable to set process ACL: %s",
|
||||
*error = dupprintf("Unable to set process ACL: %s",
|
||||
win_strerror(GetLastError()));
|
||||
goto cleanup;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ret=true;
|
||||
|
||||
|
||||
cleanup:
|
||||
if (!ret) {
|
||||
if (acl) {
|
||||
|
@ -16,23 +16,23 @@
|
||||
* Functions loaded from advapi32.dll.
|
||||
*/
|
||||
DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, OpenProcessToken,
|
||||
(HANDLE, DWORD, PHANDLE));
|
||||
(HANDLE, DWORD, PHANDLE));
|
||||
DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, GetTokenInformation,
|
||||
(HANDLE, TOKEN_INFORMATION_CLASS,
|
||||
(HANDLE, TOKEN_INFORMATION_CLASS,
|
||||
LPVOID, DWORD, PDWORD));
|
||||
DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, InitializeSecurityDescriptor,
|
||||
(PSECURITY_DESCRIPTOR, DWORD));
|
||||
(PSECURITY_DESCRIPTOR, DWORD));
|
||||
DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, SetSecurityDescriptorOwner,
|
||||
(PSECURITY_DESCRIPTOR, PSID, BOOL));
|
||||
(PSECURITY_DESCRIPTOR, PSID, BOOL));
|
||||
DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, GetSecurityInfo,
|
||||
(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
|
||||
PSID *, PSID *, PACL *, PACL *,
|
||||
PSECURITY_DESCRIPTOR *));
|
||||
(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
|
||||
PSID *, PSID *, PACL *, PACL *,
|
||||
PSECURITY_DESCRIPTOR *));
|
||||
DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, SetSecurityInfo,
|
||||
(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
|
||||
PSID, PSID, PACL, PACL));
|
||||
(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
|
||||
PSID, PSID, PACL, PACL));
|
||||
DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, SetEntriesInAclA,
|
||||
(ULONG, PEXPLICIT_ACCESS, PACL, PACL *));
|
||||
(ULONG, PEXPLICIT_ACCESS, PACL, PACL *));
|
||||
bool got_advapi(void);
|
||||
|
||||
/*
|
||||
|
294
windows/winser.c
294
windows/winser.c
@ -25,18 +25,18 @@ struct Serial {
|
||||
static void serial_terminate(Serial *serial)
|
||||
{
|
||||
if (serial->out) {
|
||||
handle_free(serial->out);
|
||||
serial->out = NULL;
|
||||
handle_free(serial->out);
|
||||
serial->out = NULL;
|
||||
}
|
||||
if (serial->in) {
|
||||
handle_free(serial->in);
|
||||
serial->in = NULL;
|
||||
handle_free(serial->in);
|
||||
serial->in = NULL;
|
||||
}
|
||||
if (serial->port != INVALID_HANDLE_VALUE) {
|
||||
if (serial->break_in_progress)
|
||||
ClearCommBreak(serial->port);
|
||||
CloseHandle(serial->port);
|
||||
serial->port = INVALID_HANDLE_VALUE;
|
||||
if (serial->break_in_progress)
|
||||
ClearCommBreak(serial->port);
|
||||
CloseHandle(serial->port);
|
||||
serial->port = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,31 +45,31 @@ static size_t serial_gotdata(
|
||||
{
|
||||
Serial *serial = (Serial *)handle_get_privdata(h);
|
||||
if (err || len == 0) {
|
||||
const char *error_msg;
|
||||
const char *error_msg;
|
||||
|
||||
/*
|
||||
* Currently, len==0 should never happen because we're
|
||||
* ignoring EOFs. However, it seems not totally impossible
|
||||
* that this same back end might be usable to talk to named
|
||||
* pipes or some other non-serial device, in which case EOF
|
||||
* may become meaningful here.
|
||||
*/
|
||||
/*
|
||||
* Currently, len==0 should never happen because we're
|
||||
* ignoring EOFs. However, it seems not totally impossible
|
||||
* that this same back end might be usable to talk to named
|
||||
* pipes or some other non-serial device, in which case EOF
|
||||
* may become meaningful here.
|
||||
*/
|
||||
if (!err)
|
||||
error_msg = "End of file reading from serial device";
|
||||
else
|
||||
error_msg = "Error reading from serial device";
|
||||
error_msg = "End of file reading from serial device";
|
||||
else
|
||||
error_msg = "Error reading from serial device";
|
||||
|
||||
serial_terminate(serial);
|
||||
serial_terminate(serial);
|
||||
|
||||
seat_notify_remote_exit(serial->seat);
|
||||
seat_notify_remote_exit(serial->seat);
|
||||
|
||||
logevent(serial->logctx, error_msg);
|
||||
|
||||
seat_connection_fatal(serial->seat, "%s", error_msg);
|
||||
seat_connection_fatal(serial->seat, "%s", error_msg);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
} else {
|
||||
return seat_stdout(serial->seat, data, len);
|
||||
return seat_stdout(serial->seat, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,17 +77,17 @@ static void serial_sentdata(struct handle *h, size_t new_backlog, int err)
|
||||
{
|
||||
Serial *serial = (Serial *)handle_get_privdata(h);
|
||||
if (err) {
|
||||
const char *error_msg = "Error writing to serial device";
|
||||
const char *error_msg = "Error writing to serial device";
|
||||
|
||||
serial_terminate(serial);
|
||||
serial_terminate(serial);
|
||||
|
||||
seat_notify_remote_exit(serial->seat);
|
||||
seat_notify_remote_exit(serial->seat);
|
||||
|
||||
logevent(serial->logctx, error_msg);
|
||||
|
||||
seat_connection_fatal(serial->seat, "%s", error_msg);
|
||||
seat_connection_fatal(serial->seat, "%s", error_msg);
|
||||
} else {
|
||||
serial->bufsize = new_backlog;
|
||||
serial->bufsize = new_backlog;
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,81 +103,81 @@ static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
|
||||
* device instead of a serial port.
|
||||
*/
|
||||
if (GetCommState(serport, &dcb)) {
|
||||
const char *str;
|
||||
const char *str;
|
||||
|
||||
/*
|
||||
* Boilerplate.
|
||||
*/
|
||||
dcb.fBinary = true;
|
||||
dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
dcb.fDsrSensitivity = false;
|
||||
dcb.fTXContinueOnXoff = false;
|
||||
dcb.fOutX = false;
|
||||
dcb.fInX = false;
|
||||
dcb.fErrorChar = false;
|
||||
dcb.fNull = false;
|
||||
dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
dcb.fAbortOnError = false;
|
||||
dcb.fOutxCtsFlow = false;
|
||||
dcb.fOutxDsrFlow = false;
|
||||
/*
|
||||
* Boilerplate.
|
||||
*/
|
||||
dcb.fBinary = true;
|
||||
dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
||||
dcb.fDsrSensitivity = false;
|
||||
dcb.fTXContinueOnXoff = false;
|
||||
dcb.fOutX = false;
|
||||
dcb.fInX = false;
|
||||
dcb.fErrorChar = false;
|
||||
dcb.fNull = false;
|
||||
dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
||||
dcb.fAbortOnError = false;
|
||||
dcb.fOutxCtsFlow = false;
|
||||
dcb.fOutxDsrFlow = false;
|
||||
|
||||
/*
|
||||
* Configurable parameters.
|
||||
*/
|
||||
dcb.BaudRate = conf_get_int(conf, CONF_serspeed);
|
||||
/*
|
||||
* Configurable parameters.
|
||||
*/
|
||||
dcb.BaudRate = conf_get_int(conf, CONF_serspeed);
|
||||
logeventf(serial->logctx, "Configuring baud rate %lu", dcb.BaudRate);
|
||||
|
||||
dcb.ByteSize = conf_get_int(conf, CONF_serdatabits);
|
||||
dcb.ByteSize = conf_get_int(conf, CONF_serdatabits);
|
||||
logeventf(serial->logctx, "Configuring %u data bits", dcb.ByteSize);
|
||||
|
||||
switch (conf_get_int(conf, CONF_serstopbits)) {
|
||||
case 2: dcb.StopBits = ONESTOPBIT; str = "1"; break;
|
||||
case 3: dcb.StopBits = ONE5STOPBITS; str = "1.5"; break;
|
||||
case 4: dcb.StopBits = TWOSTOPBITS; str = "2"; break;
|
||||
default: return "Invalid number of stop bits (need 1, 1.5 or 2)";
|
||||
}
|
||||
switch (conf_get_int(conf, CONF_serstopbits)) {
|
||||
case 2: dcb.StopBits = ONESTOPBIT; str = "1"; break;
|
||||
case 3: dcb.StopBits = ONE5STOPBITS; str = "1.5"; break;
|
||||
case 4: dcb.StopBits = TWOSTOPBITS; str = "2"; break;
|
||||
default: return "Invalid number of stop bits (need 1, 1.5 or 2)";
|
||||
}
|
||||
logeventf(serial->logctx, "Configuring %s data bits", str);
|
||||
|
||||
switch (conf_get_int(conf, CONF_serparity)) {
|
||||
case SER_PAR_NONE: dcb.Parity = NOPARITY; str = "no"; break;
|
||||
case SER_PAR_ODD: dcb.Parity = ODDPARITY; str = "odd"; break;
|
||||
case SER_PAR_EVEN: dcb.Parity = EVENPARITY; str = "even"; break;
|
||||
case SER_PAR_MARK: dcb.Parity = MARKPARITY; str = "mark"; break;
|
||||
case SER_PAR_SPACE: dcb.Parity = SPACEPARITY; str = "space"; break;
|
||||
}
|
||||
switch (conf_get_int(conf, CONF_serparity)) {
|
||||
case SER_PAR_NONE: dcb.Parity = NOPARITY; str = "no"; break;
|
||||
case SER_PAR_ODD: dcb.Parity = ODDPARITY; str = "odd"; break;
|
||||
case SER_PAR_EVEN: dcb.Parity = EVENPARITY; str = "even"; break;
|
||||
case SER_PAR_MARK: dcb.Parity = MARKPARITY; str = "mark"; break;
|
||||
case SER_PAR_SPACE: dcb.Parity = SPACEPARITY; str = "space"; break;
|
||||
}
|
||||
logeventf(serial->logctx, "Configuring %s parity", str);
|
||||
|
||||
switch (conf_get_int(conf, CONF_serflow)) {
|
||||
case SER_FLOW_NONE:
|
||||
str = "no";
|
||||
break;
|
||||
case SER_FLOW_XONXOFF:
|
||||
dcb.fOutX = dcb.fInX = true;
|
||||
str = "XON/XOFF";
|
||||
break;
|
||||
case SER_FLOW_RTSCTS:
|
||||
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
||||
dcb.fOutxCtsFlow = true;
|
||||
str = "RTS/CTS";
|
||||
break;
|
||||
case SER_FLOW_DSRDTR:
|
||||
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
|
||||
dcb.fOutxDsrFlow = true;
|
||||
str = "DSR/DTR";
|
||||
break;
|
||||
}
|
||||
switch (conf_get_int(conf, CONF_serflow)) {
|
||||
case SER_FLOW_NONE:
|
||||
str = "no";
|
||||
break;
|
||||
case SER_FLOW_XONXOFF:
|
||||
dcb.fOutX = dcb.fInX = true;
|
||||
str = "XON/XOFF";
|
||||
break;
|
||||
case SER_FLOW_RTSCTS:
|
||||
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
||||
dcb.fOutxCtsFlow = true;
|
||||
str = "RTS/CTS";
|
||||
break;
|
||||
case SER_FLOW_DSRDTR:
|
||||
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
|
||||
dcb.fOutxDsrFlow = true;
|
||||
str = "DSR/DTR";
|
||||
break;
|
||||
}
|
||||
logeventf(serial->logctx, "Configuring %s flow control", str);
|
||||
|
||||
if (!SetCommState(serport, &dcb))
|
||||
return "Unable to configure serial port";
|
||||
if (!SetCommState(serport, &dcb))
|
||||
return "Unable to configure serial port";
|
||||
|
||||
timeouts.ReadIntervalTimeout = 1;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
timeouts.ReadTotalTimeoutConstant = 0;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
timeouts.WriteTotalTimeoutConstant = 0;
|
||||
if (!SetCommTimeouts(serport, &timeouts))
|
||||
return "Unable to configure serial timeouts";
|
||||
timeouts.ReadIntervalTimeout = 1;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
timeouts.ReadTotalTimeoutConstant = 0;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
timeouts.WriteTotalTimeoutConstant = 0;
|
||||
if (!SetCommTimeouts(serport, &timeouts))
|
||||
return "Unable to configure serial timeouts";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -185,7 +185,7 @@ static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
|
||||
|
||||
/*
|
||||
* Called to set up the serial connection.
|
||||
*
|
||||
*
|
||||
* Returns an error message, or NULL on success.
|
||||
*
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
@ -194,7 +194,7 @@ static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
|
||||
static const char *serial_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port,
|
||||
char **realhost, bool nodelay, bool keepalive)
|
||||
char **realhost, bool nodelay, bool keepalive)
|
||||
{
|
||||
Serial *serial;
|
||||
HANDLE serport;
|
||||
@ -219,50 +219,50 @@ static const char *serial_init(Seat *seat, Backend **backend_handle,
|
||||
logeventf(serial->logctx, "Opening serial device %s", serline);
|
||||
|
||||
{
|
||||
/*
|
||||
* Munge the string supplied by the user into a Windows filename.
|
||||
*
|
||||
* Windows supports opening a few "legacy" devices (including
|
||||
* COM1-9) by specifying their names verbatim as a filename to
|
||||
* open. (Thus, no files can ever have these names. See
|
||||
* <http://msdn2.microsoft.com/en-us/library/aa365247.aspx>
|
||||
* ("Naming a File") for the complete list of reserved names.)
|
||||
*
|
||||
* However, this doesn't let you get at devices COM10 and above.
|
||||
* For that, you need to specify a filename like "\\.\COM10".
|
||||
* This is also necessary for special serial and serial-like
|
||||
* devices such as \\.\WCEUSBSH001. It also works for the "legacy"
|
||||
* names, so you can do \\.\COM1 (verified as far back as Win95).
|
||||
* See <http://msdn2.microsoft.com/en-us/library/aa363858.aspx>
|
||||
* (CreateFile() docs).
|
||||
*
|
||||
* So, we believe that prepending "\\.\" should always be the
|
||||
* Right Thing. However, just in case someone finds something to
|
||||
* talk to that doesn't exist under there, if the serial line
|
||||
* contains a backslash, we use it verbatim. (This also lets
|
||||
* existing configurations using \\.\ continue working.)
|
||||
*/
|
||||
char *serfilename =
|
||||
dupprintf("%s%s", strchr(serline, '\\') ? "" : "\\\\.\\", serline);
|
||||
serport = CreateFile(serfilename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
sfree(serfilename);
|
||||
/*
|
||||
* Munge the string supplied by the user into a Windows filename.
|
||||
*
|
||||
* Windows supports opening a few "legacy" devices (including
|
||||
* COM1-9) by specifying their names verbatim as a filename to
|
||||
* open. (Thus, no files can ever have these names. See
|
||||
* <http://msdn2.microsoft.com/en-us/library/aa365247.aspx>
|
||||
* ("Naming a File") for the complete list of reserved names.)
|
||||
*
|
||||
* However, this doesn't let you get at devices COM10 and above.
|
||||
* For that, you need to specify a filename like "\\.\COM10".
|
||||
* This is also necessary for special serial and serial-like
|
||||
* devices such as \\.\WCEUSBSH001. It also works for the "legacy"
|
||||
* names, so you can do \\.\COM1 (verified as far back as Win95).
|
||||
* See <http://msdn2.microsoft.com/en-us/library/aa363858.aspx>
|
||||
* (CreateFile() docs).
|
||||
*
|
||||
* So, we believe that prepending "\\.\" should always be the
|
||||
* Right Thing. However, just in case someone finds something to
|
||||
* talk to that doesn't exist under there, if the serial line
|
||||
* contains a backslash, we use it verbatim. (This also lets
|
||||
* existing configurations using \\.\ continue working.)
|
||||
*/
|
||||
char *serfilename =
|
||||
dupprintf("%s%s", strchr(serline, '\\') ? "" : "\\\\.\\", serline);
|
||||
serport = CreateFile(serfilename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
sfree(serfilename);
|
||||
}
|
||||
|
||||
if (serport == INVALID_HANDLE_VALUE)
|
||||
return "Unable to open serial port";
|
||||
return "Unable to open serial port";
|
||||
|
||||
err = serial_configure(serial, serport, conf);
|
||||
if (err)
|
||||
return err;
|
||||
return err;
|
||||
|
||||
serial->port = serport;
|
||||
serial->out = handle_output_new(serport, serial_sentdata, serial,
|
||||
HANDLE_FLAG_OVERLAPPED);
|
||||
HANDLE_FLAG_OVERLAPPED);
|
||||
serial->in = handle_input_new(serport, serial_gotdata, serial,
|
||||
HANDLE_FLAG_OVERLAPPED |
|
||||
HANDLE_FLAG_IGNOREEOF |
|
||||
HANDLE_FLAG_UNITBUFFER);
|
||||
HANDLE_FLAG_OVERLAPPED |
|
||||
HANDLE_FLAG_IGNOREEOF |
|
||||
HANDLE_FLAG_UNITBUFFER);
|
||||
|
||||
*realhost = dupstr(serline);
|
||||
|
||||
@ -303,7 +303,7 @@ static size_t serial_send(Backend *be, const char *buf, size_t len)
|
||||
Serial *serial = container_of(be, Serial, backend);
|
||||
|
||||
if (serial->out == NULL)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
serial->bufsize = handle_write(serial->out, buf, len);
|
||||
return serial->bufsize;
|
||||
@ -332,8 +332,8 @@ static void serbreak_timer(void *ctx, unsigned long now)
|
||||
Serial *serial = (Serial *)ctx;
|
||||
|
||||
if (now == serial->clearbreak_time && serial->port) {
|
||||
ClearCommBreak(serial->port);
|
||||
serial->break_in_progress = false;
|
||||
ClearCommBreak(serial->port);
|
||||
serial->break_in_progress = false;
|
||||
logevent(serial->logctx, "Finished serial break");
|
||||
}
|
||||
}
|
||||
@ -347,20 +347,20 @@ static void serial_special(Backend *be, SessionSpecialCode code, int arg)
|
||||
|
||||
if (serial->port && code == SS_BRK) {
|
||||
logevent(serial->logctx, "Starting serial break at user request");
|
||||
SetCommBreak(serial->port);
|
||||
/*
|
||||
* To send a serial break on Windows, we call SetCommBreak
|
||||
* to begin the break, then wait a bit, and then call
|
||||
* ClearCommBreak to finish it. Hence, I must use timing.c
|
||||
* to arrange a callback when it's time to do the latter.
|
||||
*
|
||||
* SUS says that a default break length must be between 1/4
|
||||
* and 1/2 second. FreeBSD apparently goes with 2/5 second,
|
||||
* and so will I.
|
||||
*/
|
||||
serial->clearbreak_time =
|
||||
schedule_timer(TICKSPERSEC * 2 / 5, serbreak_timer, serial);
|
||||
serial->break_in_progress = true;
|
||||
SetCommBreak(serial->port);
|
||||
/*
|
||||
* To send a serial break on Windows, we call SetCommBreak
|
||||
* to begin the break, then wait a bit, and then call
|
||||
* ClearCommBreak to finish it. Hence, I must use timing.c
|
||||
* to arrange a callback when it's time to do the latter.
|
||||
*
|
||||
* SUS says that a default break length must be between 1/4
|
||||
* and 1/2 second. FreeBSD apparently goes with 2/5 second,
|
||||
* and so will I.
|
||||
*/
|
||||
serial->clearbreak_time =
|
||||
schedule_timer(TICKSPERSEC * 2 / 5, serbreak_timer, serial);
|
||||
serial->break_in_progress = true;
|
||||
}
|
||||
|
||||
return;
|
||||
@ -373,8 +373,8 @@ static void serial_special(Backend *be, SessionSpecialCode code, int arg)
|
||||
static const SessionSpecial *serial_get_specials(Backend *be)
|
||||
{
|
||||
static const SessionSpecial specials[] = {
|
||||
{"Break", SS_BRK},
|
||||
{NULL, SS_EXITMENU}
|
||||
{"Break", SS_BRK},
|
||||
{NULL, SS_EXITMENU}
|
||||
};
|
||||
return specials;
|
||||
}
|
||||
@ -393,7 +393,7 @@ static void serial_unthrottle(Backend *be, size_t backlog)
|
||||
{
|
||||
Serial *serial = container_of(be, Serial, backend);
|
||||
if (serial->in)
|
||||
handle_unthrottle(serial->in, backlog);
|
||||
handle_unthrottle(serial->in, backlog);
|
||||
}
|
||||
|
||||
static bool serial_ldisc(Backend *be, int option)
|
||||
|
@ -17,7 +17,7 @@ int filexfer_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input)
|
||||
int ret;
|
||||
ret = cmdline_get_passwd_input(p);
|
||||
if (ret == -1)
|
||||
ret = console_get_userpass_input(p);
|
||||
ret = console_get_userpass_input(p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -40,17 +40,17 @@ char *psftp_lcd(char *dir)
|
||||
char *ret = NULL;
|
||||
|
||||
if (!SetCurrentDirectory(dir)) {
|
||||
LPVOID message;
|
||||
int i;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&message, 0, NULL);
|
||||
i = strcspn((char *)message, "\n");
|
||||
ret = dupprintf("%.*s", i, (LPCTSTR)message);
|
||||
LocalFree(message);
|
||||
LPVOID message;
|
||||
int i;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&message, 0, NULL);
|
||||
i = strcspn((char *)message, "\n");
|
||||
ret = dupprintf("%.*s", i, (LPCTSTR)message);
|
||||
LocalFree(message);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -65,7 +65,7 @@ char *psftp_getcwd(void)
|
||||
char *ret = snewn(256, char);
|
||||
size_t len = GetCurrentDirectory(256, ret);
|
||||
if (len > 256)
|
||||
ret = sresize(ret, len, char);
|
||||
ret = sresize(ret, len, char);
|
||||
GetCurrentDirectory(len, ret);
|
||||
return ret;
|
||||
}
|
||||
@ -94,16 +94,16 @@ struct RFile {
|
||||
};
|
||||
|
||||
RFile *open_existing_file(const char *name, uint64_t *size,
|
||||
unsigned long *mtime, unsigned long *atime,
|
||||
unsigned long *mtime, unsigned long *atime,
|
||||
long *perms)
|
||||
{
|
||||
HANDLE h;
|
||||
RFile *ret;
|
||||
|
||||
h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, 0, 0);
|
||||
OPEN_EXISTING, 0, 0);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ret = snew(RFile);
|
||||
ret->h = h;
|
||||
@ -115,12 +115,12 @@ RFile *open_existing_file(const char *name, uint64_t *size,
|
||||
}
|
||||
|
||||
if (mtime || atime) {
|
||||
FILETIME actime, wrtime;
|
||||
GetFileTime(h, NULL, &actime, &wrtime);
|
||||
if (atime)
|
||||
TIME_WIN_TO_POSIX(actime, *atime);
|
||||
if (mtime)
|
||||
TIME_WIN_TO_POSIX(wrtime, *mtime);
|
||||
FILETIME actime, wrtime;
|
||||
GetFileTime(h, NULL, &actime, &wrtime);
|
||||
if (atime)
|
||||
TIME_WIN_TO_POSIX(actime, *atime);
|
||||
if (mtime)
|
||||
TIME_WIN_TO_POSIX(wrtime, *mtime);
|
||||
}
|
||||
|
||||
if (perms)
|
||||
@ -133,9 +133,9 @@ int read_from_file(RFile *f, void *buffer, int length)
|
||||
{
|
||||
DWORD read;
|
||||
if (!ReadFile(f->h, buffer, length, &read, NULL))
|
||||
return -1; /* error */
|
||||
return -1; /* error */
|
||||
else
|
||||
return read;
|
||||
return read;
|
||||
}
|
||||
|
||||
void close_rfile(RFile *f)
|
||||
@ -154,9 +154,9 @@ WFile *open_new_file(const char *name, long perms)
|
||||
WFile *ret;
|
||||
|
||||
h = CreateFile(name, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ret = snew(WFile);
|
||||
ret->h = h;
|
||||
@ -170,9 +170,9 @@ WFile *open_existing_wfile(const char *name, uint64_t *size)
|
||||
WFile *ret;
|
||||
|
||||
h = CreateFile(name, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, 0, 0);
|
||||
OPEN_EXISTING, 0, 0);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ret = snew(WFile);
|
||||
ret->h = h;
|
||||
@ -190,9 +190,9 @@ int write_to_file(WFile *f, void *buffer, int length)
|
||||
{
|
||||
DWORD written;
|
||||
if (!WriteFile(f->h, buffer, length, &written, NULL))
|
||||
return -1; /* error */
|
||||
return -1; /* error */
|
||||
else
|
||||
return written;
|
||||
return written;
|
||||
}
|
||||
|
||||
void set_file_times(WFile *f, unsigned long mtime, unsigned long atime)
|
||||
@ -217,27 +217,27 @@ int seek_file(WFile *f, uint64_t offset, int whence)
|
||||
|
||||
switch (whence) {
|
||||
case FROM_START:
|
||||
movemethod = FILE_BEGIN;
|
||||
break;
|
||||
movemethod = FILE_BEGIN;
|
||||
break;
|
||||
case FROM_CURRENT:
|
||||
movemethod = FILE_CURRENT;
|
||||
break;
|
||||
movemethod = FILE_CURRENT;
|
||||
break;
|
||||
case FROM_END:
|
||||
movemethod = FILE_END;
|
||||
break;
|
||||
movemethod = FILE_END;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
LONG lo = offset & 0xFFFFFFFFU, hi = offset >> 32;
|
||||
SetFilePointer(f->h, lo, &hi, movemethod);
|
||||
}
|
||||
|
||||
|
||||
if (GetLastError() != NO_ERROR)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t get_file_posn(WFile *f)
|
||||
@ -254,11 +254,11 @@ int file_type(const char *name)
|
||||
attr = GetFileAttributes(name);
|
||||
/* We know of no `weird' files under Windows. */
|
||||
if (attr == (DWORD)-1)
|
||||
return FILE_TYPE_NONEXISTENT;
|
||||
return FILE_TYPE_NONEXISTENT;
|
||||
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
return FILE_TYPE_DIRECTORY;
|
||||
return FILE_TYPE_DIRECTORY;
|
||||
else
|
||||
return FILE_TYPE_FILE;
|
||||
return FILE_TYPE_FILE;
|
||||
}
|
||||
|
||||
struct DirHandle {
|
||||
@ -278,7 +278,7 @@ DirHandle *open_directory(const char *name, const char **errmsg)
|
||||
h = FindFirstFile(findfile, &fdat);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
*errmsg = win_strerror(GetLastError());
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
sfree(findfile);
|
||||
|
||||
@ -292,37 +292,37 @@ char *read_filename(DirHandle *dir)
|
||||
{
|
||||
do {
|
||||
|
||||
if (!dir->name) {
|
||||
WIN32_FIND_DATA fdat;
|
||||
if (!FindNextFile(dir->h, &fdat))
|
||||
return NULL;
|
||||
else
|
||||
dir->name = dupstr(fdat.cFileName);
|
||||
}
|
||||
if (!dir->name) {
|
||||
WIN32_FIND_DATA fdat;
|
||||
if (!FindNextFile(dir->h, &fdat))
|
||||
return NULL;
|
||||
else
|
||||
dir->name = dupstr(fdat.cFileName);
|
||||
}
|
||||
|
||||
assert(dir->name);
|
||||
if (dir->name[0] == '.' &&
|
||||
(dir->name[1] == '\0' ||
|
||||
(dir->name[1] == '.' && dir->name[2] == '\0'))) {
|
||||
sfree(dir->name);
|
||||
dir->name = NULL;
|
||||
}
|
||||
assert(dir->name);
|
||||
if (dir->name[0] == '.' &&
|
||||
(dir->name[1] == '\0' ||
|
||||
(dir->name[1] == '.' && dir->name[2] == '\0'))) {
|
||||
sfree(dir->name);
|
||||
dir->name = NULL;
|
||||
}
|
||||
|
||||
} while (!dir->name);
|
||||
|
||||
if (dir->name) {
|
||||
char *ret = dir->name;
|
||||
dir->name = NULL;
|
||||
return ret;
|
||||
char *ret = dir->name;
|
||||
dir->name = NULL;
|
||||
return ret;
|
||||
} else
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void close_directory(DirHandle *dir)
|
||||
{
|
||||
FindClose(dir->h);
|
||||
if (dir->name)
|
||||
sfree(dir->name);
|
||||
sfree(dir->name);
|
||||
sfree(dir);
|
||||
}
|
||||
|
||||
@ -333,12 +333,12 @@ int test_wildcard(const char *name, bool cmdline)
|
||||
|
||||
/* First see if the exact name exists. */
|
||||
if (GetFileAttributes(name) != (DWORD)-1)
|
||||
return WCTYPE_FILENAME;
|
||||
return WCTYPE_FILENAME;
|
||||
|
||||
/* Otherwise see if a wildcard match finds anything. */
|
||||
fh = FindFirstFile(name, &fdat);
|
||||
if (fh == INVALID_HANDLE_VALUE)
|
||||
return WCTYPE_NONEXISTENT;
|
||||
return WCTYPE_NONEXISTENT;
|
||||
|
||||
FindClose(fh);
|
||||
return WCTYPE_WILDCARD;
|
||||
@ -367,8 +367,8 @@ char *stripslashes(const char *str, bool local)
|
||||
if (p) str = p+1;
|
||||
|
||||
if (local) {
|
||||
p = strrchr(str, '\\');
|
||||
if (p) str = p+1;
|
||||
p = strrchr(str, '\\');
|
||||
if (p) str = p+1;
|
||||
}
|
||||
|
||||
return (char *)str;
|
||||
@ -383,7 +383,7 @@ WildcardMatcher *begin_wildcard_matching(const char *name)
|
||||
|
||||
h = FindFirstFile(name, &fdat);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ret = snew(WildcardMatcher);
|
||||
ret->h = h;
|
||||
@ -391,11 +391,11 @@ WildcardMatcher *begin_wildcard_matching(const char *name)
|
||||
last = stripslashes(ret->srcpath, true);
|
||||
*last = '\0';
|
||||
if (fdat.cFileName[0] == '.' &&
|
||||
(fdat.cFileName[1] == '\0' ||
|
||||
(fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
|
||||
ret->name = NULL;
|
||||
(fdat.cFileName[1] == '\0' ||
|
||||
(fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
|
||||
ret->name = NULL;
|
||||
else
|
||||
ret->name = dupcat(ret->srcpath, fdat.cFileName, NULL);
|
||||
ret->name = dupcat(ret->srcpath, fdat.cFileName, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -403,32 +403,32 @@ WildcardMatcher *begin_wildcard_matching(const char *name)
|
||||
char *wildcard_get_filename(WildcardMatcher *dir)
|
||||
{
|
||||
while (!dir->name) {
|
||||
WIN32_FIND_DATA fdat;
|
||||
WIN32_FIND_DATA fdat;
|
||||
|
||||
if (!FindNextFile(dir->h, &fdat))
|
||||
return NULL;
|
||||
if (!FindNextFile(dir->h, &fdat))
|
||||
return NULL;
|
||||
|
||||
if (fdat.cFileName[0] == '.' &&
|
||||
(fdat.cFileName[1] == '\0' ||
|
||||
(fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
|
||||
dir->name = NULL;
|
||||
else
|
||||
dir->name = dupcat(dir->srcpath, fdat.cFileName, NULL);
|
||||
if (fdat.cFileName[0] == '.' &&
|
||||
(fdat.cFileName[1] == '\0' ||
|
||||
(fdat.cFileName[1] == '.' && fdat.cFileName[2] == '\0')))
|
||||
dir->name = NULL;
|
||||
else
|
||||
dir->name = dupcat(dir->srcpath, fdat.cFileName, NULL);
|
||||
}
|
||||
|
||||
if (dir->name) {
|
||||
char *ret = dir->name;
|
||||
dir->name = NULL;
|
||||
return ret;
|
||||
char *ret = dir->name;
|
||||
dir->name = NULL;
|
||||
return ret;
|
||||
} else
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void finish_wildcard_matching(WildcardMatcher *dir)
|
||||
{
|
||||
FindClose(dir->h);
|
||||
if (dir->name)
|
||||
sfree(dir->name);
|
||||
sfree(dir->name);
|
||||
sfree(dir->srcpath);
|
||||
sfree(dir);
|
||||
}
|
||||
@ -436,10 +436,10 @@ void finish_wildcard_matching(WildcardMatcher *dir)
|
||||
bool vet_filename(const char *name)
|
||||
{
|
||||
if (strchr(name, '/') || strchr(name, '\\') || strchr(name, ':'))
|
||||
return false;
|
||||
return false;
|
||||
|
||||
if (!name[strspn(name, ".")]) /* entirely composed of dots */
|
||||
return false;
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -471,26 +471,26 @@ char *do_select(SOCKET skt, bool startup)
|
||||
{
|
||||
int events;
|
||||
if (startup)
|
||||
sftp_ssh_socket = skt;
|
||||
sftp_ssh_socket = skt;
|
||||
else
|
||||
sftp_ssh_socket = INVALID_SOCKET;
|
||||
sftp_ssh_socket = INVALID_SOCKET;
|
||||
|
||||
if (p_WSAEventSelect) {
|
||||
if (startup) {
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
netevent = CreateEvent(NULL, false, false, NULL);
|
||||
} else {
|
||||
events = 0;
|
||||
}
|
||||
if (p_WSAEventSelect(skt, netevent, events) == SOCKET_ERROR) {
|
||||
switch (p_WSAGetLastError()) {
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
default:
|
||||
return "WSAEventSelect(): unknown error";
|
||||
}
|
||||
}
|
||||
if (startup) {
|
||||
events = (FD_CONNECT | FD_READ | FD_WRITE |
|
||||
FD_OOB | FD_CLOSE | FD_ACCEPT);
|
||||
netevent = CreateEvent(NULL, false, false, NULL);
|
||||
} else {
|
||||
events = 0;
|
||||
}
|
||||
if (p_WSAEventSelect(skt, netevent, events) == SOCKET_ERROR) {
|
||||
switch (p_WSAGetLastError()) {
|
||||
case WSAENETDOWN:
|
||||
return "Network is down";
|
||||
default:
|
||||
return "WSAEventSelect(): unknown error";
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -509,14 +509,14 @@ int do_eventsel_loop(HANDLE other_event)
|
||||
ticks = 0;
|
||||
next = now;
|
||||
} else if (run_timers(now, &next)) {
|
||||
then = now;
|
||||
now = GETTICKCOUNT();
|
||||
if (now - then > next - then)
|
||||
ticks = 0;
|
||||
else
|
||||
ticks = next - now;
|
||||
then = now;
|
||||
now = GETTICKCOUNT();
|
||||
if (now - then > next - then)
|
||||
ticks = 0;
|
||||
else
|
||||
ticks = next - now;
|
||||
} else {
|
||||
ticks = INFINITE;
|
||||
ticks = INFINITE;
|
||||
/* no need to initialise next here because we can never get
|
||||
* WAIT_TIMEOUT */
|
||||
}
|
||||
@ -526,75 +526,75 @@ int do_eventsel_loop(HANDLE other_event)
|
||||
nallhandles = nhandles;
|
||||
|
||||
if (netevent != INVALID_HANDLE_VALUE)
|
||||
handles[netindex = nallhandles++] = netevent;
|
||||
handles[netindex = nallhandles++] = netevent;
|
||||
else
|
||||
netindex = -1;
|
||||
netindex = -1;
|
||||
if (other_event != INVALID_HANDLE_VALUE)
|
||||
handles[otherindex = nallhandles++] = other_event;
|
||||
handles[otherindex = nallhandles++] = other_event;
|
||||
else
|
||||
otherindex = -1;
|
||||
otherindex = -1;
|
||||
|
||||
n = WaitForMultipleObjects(nallhandles, handles, false, ticks);
|
||||
|
||||
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
|
||||
handle_got_event(handles[n - WAIT_OBJECT_0]);
|
||||
handle_got_event(handles[n - WAIT_OBJECT_0]);
|
||||
} else if (netindex >= 0 && n == WAIT_OBJECT_0 + netindex) {
|
||||
WSANETWORKEVENTS things;
|
||||
SOCKET socket;
|
||||
int i, socketstate;
|
||||
WSANETWORKEVENTS things;
|
||||
SOCKET socket;
|
||||
int i, socketstate;
|
||||
|
||||
/*
|
||||
* We must not call select_result() for any socket
|
||||
* until we have finished enumerating within the
|
||||
* tree. This is because select_result() may close
|
||||
* the socket and modify the tree.
|
||||
*/
|
||||
/* Count the active sockets. */
|
||||
i = 0;
|
||||
for (socket = first_socket(&socketstate);
|
||||
socket != INVALID_SOCKET;
|
||||
socket = next_socket(&socketstate)) i++;
|
||||
/*
|
||||
* We must not call select_result() for any socket
|
||||
* until we have finished enumerating within the
|
||||
* tree. This is because select_result() may close
|
||||
* the socket and modify the tree.
|
||||
*/
|
||||
/* Count the active sockets. */
|
||||
i = 0;
|
||||
for (socket = first_socket(&socketstate);
|
||||
socket != INVALID_SOCKET;
|
||||
socket = next_socket(&socketstate)) i++;
|
||||
|
||||
/* Expand the buffer if necessary. */
|
||||
sklist = snewn(i, SOCKET);
|
||||
/* Expand the buffer if necessary. */
|
||||
sklist = snewn(i, SOCKET);
|
||||
|
||||
/* Retrieve the sockets into sklist. */
|
||||
skcount = 0;
|
||||
for (socket = first_socket(&socketstate);
|
||||
socket != INVALID_SOCKET;
|
||||
socket = next_socket(&socketstate)) {
|
||||
sklist[skcount++] = socket;
|
||||
}
|
||||
/* Retrieve the sockets into sklist. */
|
||||
skcount = 0;
|
||||
for (socket = first_socket(&socketstate);
|
||||
socket != INVALID_SOCKET;
|
||||
socket = next_socket(&socketstate)) {
|
||||
sklist[skcount++] = socket;
|
||||
}
|
||||
|
||||
/* Now we're done enumerating; go through the list. */
|
||||
for (i = 0; i < skcount; i++) {
|
||||
WPARAM wp;
|
||||
socket = sklist[i];
|
||||
wp = (WPARAM) socket;
|
||||
if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) {
|
||||
static const struct { int bit, mask; } eventtypes[] = {
|
||||
{FD_CONNECT_BIT, FD_CONNECT},
|
||||
{FD_READ_BIT, FD_READ},
|
||||
{FD_CLOSE_BIT, FD_CLOSE},
|
||||
{FD_OOB_BIT, FD_OOB},
|
||||
{FD_WRITE_BIT, FD_WRITE},
|
||||
{FD_ACCEPT_BIT, FD_ACCEPT},
|
||||
};
|
||||
int e;
|
||||
/* Now we're done enumerating; go through the list. */
|
||||
for (i = 0; i < skcount; i++) {
|
||||
WPARAM wp;
|
||||
socket = sklist[i];
|
||||
wp = (WPARAM) socket;
|
||||
if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) {
|
||||
static const struct { int bit, mask; } eventtypes[] = {
|
||||
{FD_CONNECT_BIT, FD_CONNECT},
|
||||
{FD_READ_BIT, FD_READ},
|
||||
{FD_CLOSE_BIT, FD_CLOSE},
|
||||
{FD_OOB_BIT, FD_OOB},
|
||||
{FD_WRITE_BIT, FD_WRITE},
|
||||
{FD_ACCEPT_BIT, FD_ACCEPT},
|
||||
};
|
||||
int e;
|
||||
|
||||
noise_ultralight(NOISE_SOURCE_IOID, socket);
|
||||
noise_ultralight(NOISE_SOURCE_IOID, socket);
|
||||
|
||||
for (e = 0; e < lenof(eventtypes); e++)
|
||||
if (things.lNetworkEvents & eventtypes[e].mask) {
|
||||
LPARAM lp;
|
||||
int err = things.iErrorCode[eventtypes[e].bit];
|
||||
lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err);
|
||||
select_result(wp, lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (e = 0; e < lenof(eventtypes); e++)
|
||||
if (things.lNetworkEvents & eventtypes[e].mask) {
|
||||
LPARAM lp;
|
||||
int err = things.iErrorCode[eventtypes[e].bit];
|
||||
lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err);
|
||||
select_result(wp, lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sfree(sklist);
|
||||
sfree(sklist);
|
||||
}
|
||||
|
||||
sfree(handles);
|
||||
@ -602,13 +602,13 @@ int do_eventsel_loop(HANDLE other_event)
|
||||
run_toplevel_callbacks();
|
||||
|
||||
if (n == WAIT_TIMEOUT) {
|
||||
now = next;
|
||||
now = next;
|
||||
} else {
|
||||
now = GETTICKCOUNT();
|
||||
now = GETTICKCOUNT();
|
||||
}
|
||||
|
||||
if (otherindex >= 0 && n == WAIT_OBJECT_0 + otherindex)
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -625,59 +625,59 @@ int do_eventsel_loop(HANDLE other_event)
|
||||
int ssh_sftp_loop_iteration(void)
|
||||
{
|
||||
if (p_WSAEventSelect == NULL) {
|
||||
fd_set readfds;
|
||||
int ret;
|
||||
unsigned long now = GETTICKCOUNT(), then;
|
||||
fd_set readfds;
|
||||
int ret;
|
||||
unsigned long now = GETTICKCOUNT(), then;
|
||||
|
||||
if (sftp_ssh_socket == INVALID_SOCKET)
|
||||
return -1; /* doom */
|
||||
if (sftp_ssh_socket == INVALID_SOCKET)
|
||||
return -1; /* doom */
|
||||
|
||||
if (socket_writable(sftp_ssh_socket))
|
||||
select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_WRITE);
|
||||
if (socket_writable(sftp_ssh_socket))
|
||||
select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_WRITE);
|
||||
|
||||
do {
|
||||
unsigned long next;
|
||||
long ticks;
|
||||
struct timeval tv, *ptv;
|
||||
do {
|
||||
unsigned long next;
|
||||
long ticks;
|
||||
struct timeval tv, *ptv;
|
||||
|
||||
if (run_timers(now, &next)) {
|
||||
then = now;
|
||||
now = GETTICKCOUNT();
|
||||
if (now - then > next - then)
|
||||
ticks = 0;
|
||||
else
|
||||
ticks = next - now;
|
||||
tv.tv_sec = ticks / 1000;
|
||||
tv.tv_usec = ticks % 1000 * 1000;
|
||||
ptv = &tv;
|
||||
} else {
|
||||
ptv = NULL;
|
||||
}
|
||||
if (run_timers(now, &next)) {
|
||||
then = now;
|
||||
now = GETTICKCOUNT();
|
||||
if (now - then > next - then)
|
||||
ticks = 0;
|
||||
else
|
||||
ticks = next - now;
|
||||
tv.tv_sec = ticks / 1000;
|
||||
tv.tv_usec = ticks % 1000 * 1000;
|
||||
ptv = &tv;
|
||||
} else {
|
||||
ptv = NULL;
|
||||
}
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(sftp_ssh_socket, &readfds);
|
||||
ret = p_select(1, &readfds, NULL, NULL, ptv);
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(sftp_ssh_socket, &readfds);
|
||||
ret = p_select(1, &readfds, NULL, NULL, ptv);
|
||||
|
||||
if (ret < 0)
|
||||
return -1; /* doom */
|
||||
else if (ret == 0)
|
||||
now = next;
|
||||
else
|
||||
now = GETTICKCOUNT();
|
||||
if (ret < 0)
|
||||
return -1; /* doom */
|
||||
else if (ret == 0)
|
||||
now = next;
|
||||
else
|
||||
now = GETTICKCOUNT();
|
||||
|
||||
} while (ret == 0);
|
||||
} while (ret == 0);
|
||||
|
||||
select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ);
|
||||
select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
} else {
|
||||
return do_eventsel_loop(INVALID_HANDLE_VALUE);
|
||||
return do_eventsel_loop(INVALID_HANDLE_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a command line from standard input.
|
||||
*
|
||||
*
|
||||
* In the presence of WinSock 2, we can use WSAEventSelect to
|
||||
* mediate between the socket and stdin, meaning we can send
|
||||
* keepalives and respond to server events even while waiting at
|
||||
@ -711,8 +711,8 @@ char *ssh_sftp_get_cmdline(const char *prompt, bool no_fds_ok)
|
||||
fflush(stdout);
|
||||
|
||||
if ((sftp_ssh_socket == INVALID_SOCKET && no_fds_ok) ||
|
||||
p_WSAEventSelect == NULL) {
|
||||
return fgetline(stdin); /* very simple */
|
||||
p_WSAEventSelect == NULL) {
|
||||
return fgetline(stdin); /* very simple */
|
||||
}
|
||||
|
||||
/*
|
||||
@ -724,16 +724,16 @@ char *ssh_sftp_get_cmdline(const char *prompt, bool no_fds_ok)
|
||||
|
||||
hThread = CreateThread(NULL, 0, command_read_thread, ctx, 0, &threadid);
|
||||
if (!hThread) {
|
||||
CloseHandle(ctx->event);
|
||||
fprintf(stderr, "Unable to create command input thread\n");
|
||||
cleanup_exit(1);
|
||||
CloseHandle(ctx->event);
|
||||
fprintf(stderr, "Unable to create command input thread\n");
|
||||
cleanup_exit(1);
|
||||
}
|
||||
|
||||
do {
|
||||
ret = do_eventsel_loop(ctx->event);
|
||||
ret = do_eventsel_loop(ctx->event);
|
||||
|
||||
/* Error return can only occur if netevent==NULL, and it ain't. */
|
||||
assert(ret >= 0);
|
||||
/* Error return can only occur if netevent==NULL, and it ain't. */
|
||||
assert(ret >= 0);
|
||||
} while (ret == 0);
|
||||
|
||||
CloseHandle(hThread);
|
||||
|
@ -24,8 +24,8 @@ static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
|
||||
|
||||
static bool tried_shgetfolderpath = false;
|
||||
static HMODULE shell32_module = NULL;
|
||||
DECL_WINDOWS_FUNCTION(static, HRESULT, SHGetFolderPathA,
|
||||
(HWND, int, HANDLE, DWORD, LPSTR));
|
||||
DECL_WINDOWS_FUNCTION(static, HRESULT, SHGetFolderPathA,
|
||||
(HWND, int, HANDLE, DWORD, LPSTR));
|
||||
|
||||
struct settings_w {
|
||||
HKEY sesskey;
|
||||
@ -40,25 +40,25 @@ settings_w *open_settings_w(const char *sessionname, char **errmsg)
|
||||
*errmsg = NULL;
|
||||
|
||||
if (!sessionname || !*sessionname)
|
||||
sessionname = "Default Settings";
|
||||
sessionname = "Default Settings";
|
||||
|
||||
sb = strbuf_new();
|
||||
escape_registry_key(sessionname, sb);
|
||||
|
||||
ret = RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
strbuf_free(sb);
|
||||
strbuf_free(sb);
|
||||
*errmsg = dupprintf("Unable to create registry key\n"
|
||||
"HKEY_CURRENT_USER\\%s", puttystr);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
ret = RegCreateKey(subkey1, sb->s, &sesskey);
|
||||
RegCloseKey(subkey1);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
*errmsg = dupprintf("Unable to create registry key\n"
|
||||
"HKEY_CURRENT_USER\\%s\\%s", puttystr, sb->s);
|
||||
strbuf_free(sb);
|
||||
return NULL;
|
||||
strbuf_free(sb);
|
||||
return NULL;
|
||||
}
|
||||
strbuf_free(sb);
|
||||
|
||||
@ -71,14 +71,14 @@ void write_setting_s(settings_w *handle, const char *key, const char *value)
|
||||
{
|
||||
if (handle)
|
||||
RegSetValueEx(handle->sesskey, key, 0, REG_SZ, (CONST BYTE *)value,
|
||||
1 + strlen(value));
|
||||
1 + strlen(value));
|
||||
}
|
||||
|
||||
void write_setting_i(settings_w *handle, const char *key, int value)
|
||||
{
|
||||
if (handle)
|
||||
RegSetValueEx(handle->sesskey, key, 0, REG_DWORD,
|
||||
(CONST BYTE *) &value, sizeof(value));
|
||||
(CONST BYTE *) &value, sizeof(value));
|
||||
}
|
||||
|
||||
void close_settings_w(settings_w *handle)
|
||||
@ -97,18 +97,18 @@ settings_r *open_settings_r(const char *sessionname)
|
||||
strbuf *sb;
|
||||
|
||||
if (!sessionname || !*sessionname)
|
||||
sessionname = "Default Settings";
|
||||
sessionname = "Default Settings";
|
||||
|
||||
sb = strbuf_new();
|
||||
escape_registry_key(sessionname, sb);
|
||||
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
|
||||
sesskey = NULL;
|
||||
sesskey = NULL;
|
||||
} else {
|
||||
if (RegOpenKey(subkey1, sb->s, &sesskey) != ERROR_SUCCESS) {
|
||||
sesskey = NULL;
|
||||
}
|
||||
RegCloseKey(subkey1);
|
||||
if (RegOpenKey(subkey1, sb->s, &sesskey) != ERROR_SUCCESS) {
|
||||
sesskey = NULL;
|
||||
}
|
||||
RegCloseKey(subkey1);
|
||||
}
|
||||
|
||||
strbuf_free(sb);
|
||||
@ -127,19 +127,19 @@ char *read_setting_s(settings_r *handle, const char *key)
|
||||
char *ret;
|
||||
|
||||
if (!handle)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
/* Find out the type and size of the data. */
|
||||
if (RegQueryValueEx(handle->sesskey, key, 0,
|
||||
&type, NULL, &size) != ERROR_SUCCESS ||
|
||||
type != REG_SZ)
|
||||
return NULL;
|
||||
&type, NULL, &size) != ERROR_SUCCESS ||
|
||||
type != REG_SZ)
|
||||
return NULL;
|
||||
|
||||
allocsize = size+1; /* allow for an extra NUL if needed */
|
||||
ret = snewn(allocsize, char);
|
||||
if (RegQueryValueEx(handle->sesskey, key, 0,
|
||||
&type, (BYTE *)ret, &size) != ERROR_SUCCESS ||
|
||||
type != REG_SZ) {
|
||||
&type, (BYTE *)ret, &size) != ERROR_SUCCESS ||
|
||||
type != REG_SZ) {
|
||||
sfree(ret);
|
||||
return NULL;
|
||||
}
|
||||
@ -157,11 +157,11 @@ int read_setting_i(settings_r *handle, const char *key, int defvalue)
|
||||
|
||||
if (!handle ||
|
||||
RegQueryValueEx(handle->sesskey, key, 0, &type,
|
||||
(BYTE *) &val, &size) != ERROR_SUCCESS ||
|
||||
size != sizeof(val) || type != REG_DWORD)
|
||||
return defvalue;
|
||||
(BYTE *) &val, &size) != ERROR_SUCCESS ||
|
||||
size != sizeof(val) || type != REG_DWORD)
|
||||
return defvalue;
|
||||
else
|
||||
return val;
|
||||
return val;
|
||||
}
|
||||
|
||||
FontSpec *read_setting_fontspec(settings_r *handle, const char *name)
|
||||
@ -173,7 +173,7 @@ FontSpec *read_setting_fontspec(settings_r *handle, const char *name)
|
||||
|
||||
fontname = read_setting_s(handle, name);
|
||||
if (!fontname)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
settingname = dupcat(name, "IsBold", NULL);
|
||||
isbold = read_setting_i(handle, settingname, -1);
|
||||
@ -226,10 +226,10 @@ Filename *read_setting_filename(settings_r *handle, const char *name)
|
||||
char *tmp = read_setting_s(handle, name);
|
||||
if (tmp) {
|
||||
Filename *ret = filename_from_str(tmp);
|
||||
sfree(tmp);
|
||||
return ret;
|
||||
sfree(tmp);
|
||||
return ret;
|
||||
} else
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void write_setting_filename(settings_w *handle,
|
||||
@ -252,7 +252,7 @@ void del_settings(const char *sessionname)
|
||||
strbuf *sb;
|
||||
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
|
||||
return;
|
||||
return;
|
||||
|
||||
sb = strbuf_new();
|
||||
escape_registry_key(sessionname, sb);
|
||||
@ -275,12 +275,12 @@ settings_e *enum_settings_start(void)
|
||||
HKEY key;
|
||||
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &key) != ERROR_SUCCESS)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ret = snew(settings_e);
|
||||
if (ret) {
|
||||
ret->key = key;
|
||||
ret->i = 0;
|
||||
ret->key = key;
|
||||
ret->i = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -316,14 +316,14 @@ void enum_settings_finish(settings_e *e)
|
||||
}
|
||||
|
||||
static void hostkey_regname(strbuf *sb, const char *hostname,
|
||||
int port, const char *keytype)
|
||||
int port, const char *keytype)
|
||||
{
|
||||
strbuf_catf(sb, "%s@%d:", keytype, port);
|
||||
escape_registry_key(hostname, sb);
|
||||
}
|
||||
|
||||
int verify_host_key(const char *hostname, int port,
|
||||
const char *keytype, const char *key)
|
||||
const char *keytype, const char *key)
|
||||
{
|
||||
char *otherstr;
|
||||
strbuf *regname;
|
||||
@ -343,9 +343,9 @@ int verify_host_key(const char *hostname, int port,
|
||||
hostkey_regname(regname, hostname, port, keytype);
|
||||
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
|
||||
&rkey) != ERROR_SUCCESS) {
|
||||
&rkey) != ERROR_SUCCESS) {
|
||||
strbuf_free(regname);
|
||||
return 1; /* key does not exist in registry */
|
||||
return 1; /* key does not exist in registry */
|
||||
}
|
||||
|
||||
readlen = len;
|
||||
@ -354,65 +354,65 @@ int verify_host_key(const char *hostname, int port,
|
||||
&type, (BYTE *)otherstr, &readlen);
|
||||
|
||||
if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA &&
|
||||
!strcmp(keytype, "rsa")) {
|
||||
/*
|
||||
* Key didn't exist. If the key type is RSA, we'll try
|
||||
* another trick, which is to look up the _old_ key format
|
||||
* under just the hostname and translate that.
|
||||
*/
|
||||
char *justhost = regname->s + 1 + strcspn(regname->s, ":");
|
||||
char *oldstyle = snewn(len + 10, char); /* safety margin */
|
||||
readlen = len;
|
||||
ret = RegQueryValueEx(rkey, justhost, NULL, &type,
|
||||
(BYTE *)oldstyle, &readlen);
|
||||
!strcmp(keytype, "rsa")) {
|
||||
/*
|
||||
* Key didn't exist. If the key type is RSA, we'll try
|
||||
* another trick, which is to look up the _old_ key format
|
||||
* under just the hostname and translate that.
|
||||
*/
|
||||
char *justhost = regname->s + 1 + strcspn(regname->s, ":");
|
||||
char *oldstyle = snewn(len + 10, char); /* safety margin */
|
||||
readlen = len;
|
||||
ret = RegQueryValueEx(rkey, justhost, NULL, &type,
|
||||
(BYTE *)oldstyle, &readlen);
|
||||
|
||||
if (ret == ERROR_SUCCESS && type == REG_SZ) {
|
||||
/*
|
||||
* The old format is two old-style bignums separated by
|
||||
* a slash. An old-style bignum is made of groups of
|
||||
* four hex digits: digits are ordered in sensible
|
||||
* (most to least significant) order within each group,
|
||||
* but groups are ordered in silly (least to most)
|
||||
* order within the bignum. The new format is two
|
||||
* ordinary C-format hex numbers (0xABCDEFG...XYZ, with
|
||||
* A nonzero except in the special case 0x0, which
|
||||
* doesn't appear anyway in RSA keys) separated by a
|
||||
* comma. All hex digits are lowercase in both formats.
|
||||
*/
|
||||
char *p = otherstr;
|
||||
char *q = oldstyle;
|
||||
int i, j;
|
||||
if (ret == ERROR_SUCCESS && type == REG_SZ) {
|
||||
/*
|
||||
* The old format is two old-style bignums separated by
|
||||
* a slash. An old-style bignum is made of groups of
|
||||
* four hex digits: digits are ordered in sensible
|
||||
* (most to least significant) order within each group,
|
||||
* but groups are ordered in silly (least to most)
|
||||
* order within the bignum. The new format is two
|
||||
* ordinary C-format hex numbers (0xABCDEFG...XYZ, with
|
||||
* A nonzero except in the special case 0x0, which
|
||||
* doesn't appear anyway in RSA keys) separated by a
|
||||
* comma. All hex digits are lowercase in both formats.
|
||||
*/
|
||||
char *p = otherstr;
|
||||
char *q = oldstyle;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
int ndigits, nwords;
|
||||
*p++ = '0';
|
||||
*p++ = 'x';
|
||||
ndigits = strcspn(q, "/"); /* find / or end of string */
|
||||
nwords = ndigits / 4;
|
||||
/* now trim ndigits to remove leading zeros */
|
||||
while (q[(ndigits - 1) ^ 3] == '0' && ndigits > 1)
|
||||
ndigits--;
|
||||
/* now move digits over to new string */
|
||||
for (j = 0; j < ndigits; j++)
|
||||
p[ndigits - 1 - j] = q[j ^ 3];
|
||||
p += ndigits;
|
||||
q += nwords * 4;
|
||||
if (*q) {
|
||||
q++; /* eat the slash */
|
||||
*p++ = ','; /* add a comma */
|
||||
}
|
||||
*p = '\0'; /* terminate the string */
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
int ndigits, nwords;
|
||||
*p++ = '0';
|
||||
*p++ = 'x';
|
||||
ndigits = strcspn(q, "/"); /* find / or end of string */
|
||||
nwords = ndigits / 4;
|
||||
/* now trim ndigits to remove leading zeros */
|
||||
while (q[(ndigits - 1) ^ 3] == '0' && ndigits > 1)
|
||||
ndigits--;
|
||||
/* now move digits over to new string */
|
||||
for (j = 0; j < ndigits; j++)
|
||||
p[ndigits - 1 - j] = q[j ^ 3];
|
||||
p += ndigits;
|
||||
q += nwords * 4;
|
||||
if (*q) {
|
||||
q++; /* eat the slash */
|
||||
*p++ = ','; /* add a comma */
|
||||
}
|
||||
*p = '\0'; /* terminate the string */
|
||||
}
|
||||
|
||||
/*
|
||||
* Now _if_ this key matches, we'll enter it in the new
|
||||
* format. If not, we'll assume something odd went
|
||||
* wrong, and hyper-cautiously do nothing.
|
||||
*/
|
||||
if (!strcmp(otherstr, key))
|
||||
RegSetValueEx(rkey, regname->s, 0, REG_SZ, (BYTE *)otherstr,
|
||||
strlen(otherstr) + 1);
|
||||
}
|
||||
/*
|
||||
* Now _if_ this key matches, we'll enter it in the new
|
||||
* format. If not, we'll assume something odd went
|
||||
* wrong, and hyper-cautiously do nothing.
|
||||
*/
|
||||
if (!strcmp(otherstr, key))
|
||||
RegSetValueEx(rkey, regname->s, 0, REG_SZ, (BYTE *)otherstr,
|
||||
strlen(otherstr) + 1);
|
||||
}
|
||||
|
||||
sfree(oldstyle);
|
||||
}
|
||||
@ -425,16 +425,16 @@ int verify_host_key(const char *hostname, int port,
|
||||
strbuf_free(regname);
|
||||
|
||||
if (ret == ERROR_MORE_DATA ||
|
||||
(ret == ERROR_SUCCESS && type == REG_SZ && compare))
|
||||
return 2; /* key is different in registry */
|
||||
(ret == ERROR_SUCCESS && type == REG_SZ && compare))
|
||||
return 2; /* key is different in registry */
|
||||
else if (ret != ERROR_SUCCESS || type != REG_SZ)
|
||||
return 1; /* key does not exist in registry */
|
||||
return 1; /* key does not exist in registry */
|
||||
else
|
||||
return 0; /* key matched OK in registry */
|
||||
return 0; /* key matched OK in registry */
|
||||
}
|
||||
|
||||
bool have_ssh_host_key(const char *hostname, int port,
|
||||
const char *keytype)
|
||||
const char *keytype)
|
||||
{
|
||||
/*
|
||||
* If we have a host key, verify_host_key will return 0 or 2.
|
||||
@ -444,7 +444,7 @@ bool have_ssh_host_key(const char *hostname, int port,
|
||||
}
|
||||
|
||||
void store_host_key(const char *hostname, int port,
|
||||
const char *keytype, const char *key)
|
||||
const char *keytype, const char *key)
|
||||
{
|
||||
strbuf *regname;
|
||||
HKEY rkey;
|
||||
@ -453,10 +453,10 @@ void store_host_key(const char *hostname, int port,
|
||||
hostkey_regname(regname, hostname, port, keytype);
|
||||
|
||||
if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
|
||||
&rkey) == ERROR_SUCCESS) {
|
||||
RegSetValueEx(rkey, regname->s, 0, REG_SZ,
|
||||
&rkey) == ERROR_SUCCESS) {
|
||||
RegSetValueEx(rkey, regname->s, 0, REG_SZ,
|
||||
(BYTE *)key, strlen(key) + 1);
|
||||
RegCloseKey(rkey);
|
||||
RegCloseKey(rkey);
|
||||
} /* else key does not exist in registry */
|
||||
|
||||
strbuf_free(regname);
|
||||
@ -473,18 +473,18 @@ static bool try_random_seed(char const *path, int action, HANDLE *ret)
|
||||
nonfatal("Unable to delete '%s': %s", path,
|
||||
win_strerror(GetLastError()));
|
||||
}
|
||||
*ret = INVALID_HANDLE_VALUE;
|
||||
return false; /* so we'll do the next ones too */
|
||||
*ret = INVALID_HANDLE_VALUE;
|
||||
return false; /* so we'll do the next ones too */
|
||||
}
|
||||
|
||||
*ret = CreateFile(path,
|
||||
action == OPEN_W ? GENERIC_WRITE : GENERIC_READ,
|
||||
action == OPEN_W ? 0 : (FILE_SHARE_READ |
|
||||
FILE_SHARE_WRITE),
|
||||
NULL,
|
||||
action == OPEN_W ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||
action == OPEN_W ? FILE_ATTRIBUTE_NORMAL : 0,
|
||||
NULL);
|
||||
action == OPEN_W ? GENERIC_WRITE : GENERIC_READ,
|
||||
action == OPEN_W ? 0 : (FILE_SHARE_READ |
|
||||
FILE_SHARE_WRITE),
|
||||
NULL,
|
||||
action == OPEN_W ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||
action == OPEN_W ? FILE_ATTRIBUTE_NORMAL : 0,
|
||||
NULL);
|
||||
|
||||
return (*ret != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
@ -504,7 +504,7 @@ static HANDLE access_random_seed(int action)
|
||||
/*
|
||||
* Iterate over a selection of possible random seed paths until
|
||||
* we find one that works.
|
||||
*
|
||||
*
|
||||
* We do this iteration separately for reading and writing,
|
||||
* meaning that we will automatically migrate random seed files
|
||||
* if a better location becomes available (by reading from the
|
||||
@ -537,27 +537,27 @@ static HANDLE access_random_seed(int action)
|
||||
* versions of Windows.
|
||||
*/
|
||||
if (!tried_shgetfolderpath) {
|
||||
/* This is likely only to bear fruit on systems with IE5+
|
||||
* installed, or WinMe/2K+. There is some faffing with
|
||||
* SHFOLDER.DLL we could do to try to find an equivalent
|
||||
* on older versions of Windows if we cared enough.
|
||||
* However, the invocation below requires IE5+ anyway,
|
||||
* so stuff that. */
|
||||
shell32_module = load_system32_dll("shell32.dll");
|
||||
GET_WINDOWS_FUNCTION(shell32_module, SHGetFolderPathA);
|
||||
tried_shgetfolderpath = true;
|
||||
/* This is likely only to bear fruit on systems with IE5+
|
||||
* installed, or WinMe/2K+. There is some faffing with
|
||||
* SHFOLDER.DLL we could do to try to find an equivalent
|
||||
* on older versions of Windows if we cared enough.
|
||||
* However, the invocation below requires IE5+ anyway,
|
||||
* so stuff that. */
|
||||
shell32_module = load_system32_dll("shell32.dll");
|
||||
GET_WINDOWS_FUNCTION(shell32_module, SHGetFolderPathA);
|
||||
tried_shgetfolderpath = true;
|
||||
}
|
||||
if (p_SHGetFolderPathA) {
|
||||
char profile[MAX_PATH + 1];
|
||||
if (SUCCEEDED(p_SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA,
|
||||
NULL, SHGFP_TYPE_CURRENT, profile)) &&
|
||||
if (SUCCEEDED(p_SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA,
|
||||
NULL, SHGFP_TYPE_CURRENT, profile)) &&
|
||||
try_random_seed_and_free(dupcat(profile, "\\PUTTY.RND",
|
||||
(const char *)NULL),
|
||||
action, &rethandle))
|
||||
return rethandle;
|
||||
|
||||
if (SUCCEEDED(p_SHGetFolderPathA(NULL, CSIDL_APPDATA,
|
||||
NULL, SHGFP_TYPE_CURRENT, profile)) &&
|
||||
if (SUCCEEDED(p_SHGetFolderPathA(NULL, CSIDL_APPDATA,
|
||||
NULL, SHGFP_TYPE_CURRENT, profile)) &&
|
||||
try_random_seed_and_free(dupcat(profile, "\\PUTTY.RND",
|
||||
(const char *)NULL),
|
||||
action, &rethandle))
|
||||
@ -569,7 +569,7 @@ static HANDLE access_random_seed(int action)
|
||||
* user's home directory.
|
||||
*/
|
||||
{
|
||||
char drv[MAX_PATH], path[MAX_PATH];
|
||||
char drv[MAX_PATH], path[MAX_PATH];
|
||||
|
||||
DWORD drvlen = GetEnvironmentVariable("HOMEDRIVE", drv, sizeof(drv));
|
||||
DWORD pathlen = GetEnvironmentVariable("HOMEPATH", path, sizeof(path));
|
||||
@ -611,16 +611,16 @@ void read_random_seed(noise_consumer_t consumer)
|
||||
HANDLE seedf = access_random_seed(OPEN_R);
|
||||
|
||||
if (seedf != INVALID_HANDLE_VALUE) {
|
||||
while (1) {
|
||||
char buf[1024];
|
||||
DWORD len;
|
||||
while (1) {
|
||||
char buf[1024];
|
||||
DWORD len;
|
||||
|
||||
if (ReadFile(seedf, buf, sizeof(buf), &len, NULL) && len)
|
||||
consumer(buf, len);
|
||||
else
|
||||
break;
|
||||
}
|
||||
CloseHandle(seedf);
|
||||
if (ReadFile(seedf, buf, sizeof(buf), &len, NULL) && len)
|
||||
consumer(buf, len);
|
||||
else
|
||||
break;
|
||||
}
|
||||
CloseHandle(seedf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -629,10 +629,10 @@ void write_random_seed(void *data, int len)
|
||||
HANDLE seedf = access_random_seed(OPEN_W);
|
||||
|
||||
if (seedf != INVALID_HANDLE_VALUE) {
|
||||
DWORD lenwritten;
|
||||
DWORD lenwritten;
|
||||
|
||||
WriteFile(seedf, data, len, &lenwritten, NULL);
|
||||
CloseHandle(seedf);
|
||||
WriteFile(seedf, data, len, &lenwritten, NULL);
|
||||
CloseHandle(seedf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,7 +659,7 @@ static int transform_jumplist_registry
|
||||
REG_OPTION_NON_VOLATILE, (KEY_READ | KEY_WRITE), NULL,
|
||||
&pjumplist_key, NULL);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
return JUMPLISTREG_ERROR_KEYOPENCREATE_FAILURE;
|
||||
return JUMPLISTREG_ERROR_KEYOPENCREATE_FAILURE;
|
||||
}
|
||||
|
||||
/* Get current list of saved sessions in the registry. */
|
||||
@ -792,7 +792,7 @@ char *get_jumplist_registry_entries (void)
|
||||
char *list_value;
|
||||
|
||||
if (transform_jumplist_registry(NULL,NULL,&list_value) != JUMPLISTREG_OK) {
|
||||
list_value = snewn(2, char);
|
||||
list_value = snewn(2, char);
|
||||
*list_value = '\0';
|
||||
*(list_value + 1) = '\0';
|
||||
}
|
||||
@ -810,11 +810,11 @@ static void registry_recursive_remove(HKEY key)
|
||||
|
||||
i = 0;
|
||||
while (RegEnumKey(key, i, name, sizeof(name)) == ERROR_SUCCESS) {
|
||||
if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS) {
|
||||
registry_recursive_remove(subkey);
|
||||
RegCloseKey(subkey);
|
||||
}
|
||||
RegDeleteKey(key, name);
|
||||
if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS) {
|
||||
registry_recursive_remove(subkey);
|
||||
RegCloseKey(subkey);
|
||||
}
|
||||
RegDeleteKey(key, name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -844,9 +844,9 @@ void cleanup_all(void)
|
||||
* Open the main PuTTY registry key and remove everything in it.
|
||||
*/
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &key) ==
|
||||
ERROR_SUCCESS) {
|
||||
registry_recursive_remove(key);
|
||||
RegCloseKey(key);
|
||||
ERROR_SUCCESS) {
|
||||
registry_recursive_remove(key);
|
||||
RegCloseKey(key);
|
||||
}
|
||||
/*
|
||||
* Now open the parent key and remove the PuTTY main key. Once
|
||||
@ -854,22 +854,22 @@ void cleanup_all(void)
|
||||
* children.
|
||||
*/
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_PARENT,
|
||||
&key) == ERROR_SUCCESS) {
|
||||
RegDeleteKey(key, PUTTY_REG_PARENT_CHILD);
|
||||
ret = RegEnumKey(key, 0, name, sizeof(name));
|
||||
RegCloseKey(key);
|
||||
/*
|
||||
* If the parent key had no other children, we must delete
|
||||
* it in its turn. That means opening the _grandparent_
|
||||
* key.
|
||||
*/
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_GPARENT,
|
||||
&key) == ERROR_SUCCESS) {
|
||||
RegDeleteKey(key, PUTTY_REG_GPARENT_CHILD);
|
||||
RegCloseKey(key);
|
||||
}
|
||||
}
|
||||
&key) == ERROR_SUCCESS) {
|
||||
RegDeleteKey(key, PUTTY_REG_PARENT_CHILD);
|
||||
ret = RegEnumKey(key, 0, name, sizeof(name));
|
||||
RegCloseKey(key);
|
||||
/*
|
||||
* If the parent key had no other children, we must delete
|
||||
* it in its turn. That means opening the _grandparent_
|
||||
* key.
|
||||
*/
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_GPARENT,
|
||||
&key) == ERROR_SUCCESS) {
|
||||
RegDeleteKey(key, PUTTY_REG_GPARENT_CHILD);
|
||||
RegCloseKey(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now we're done.
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <stdio.h> /* for FILENAME_MAX */
|
||||
#include <stdio.h> /* for FILENAME_MAX */
|
||||
|
||||
/* We use uintptr_t for Win32/Win64 portability, so we should in
|
||||
* principle include stdint.h, which defines it according to the C
|
||||
@ -66,7 +66,7 @@ struct FontSpec *fontspec_new(
|
||||
CLEARTYPE_QUALITY)
|
||||
|
||||
#define PLATFORM_IS_UTF16 /* enable UTF-16 processing when exchanging
|
||||
* wchar_t strings with environment */
|
||||
* wchar_t strings with environment */
|
||||
|
||||
#define PLATFORM_CLIPBOARDS(X) \
|
||||
X(CLIP_SYSTEM, "system clipboard") \
|
||||
@ -185,7 +185,7 @@ struct FontSpec *fontspec_new(
|
||||
|
||||
#define GETTICKCOUNT GetTickCount
|
||||
#define CURSORBLINK GetCaretBlinkTime()
|
||||
#define TICKSPERSEC 1000 /* GetTickCount returns milliseconds */
|
||||
#define TICKSPERSEC 1000 /* GetTickCount returns milliseconds */
|
||||
|
||||
#define DEFAULT_CODEPAGE CP_ACP
|
||||
#define USES_VTLINE_HACK
|
||||
@ -210,7 +210,7 @@ typedef void *Ssh_gss_name;
|
||||
* Window handles for the windows that can be running during a
|
||||
* PuTTY session.
|
||||
*/
|
||||
GLOBAL HWND hwnd; /* the main terminal window */
|
||||
GLOBAL HWND hwnd; /* the main terminal window */
|
||||
GLOBAL HWND logbox;
|
||||
|
||||
/*
|
||||
@ -299,11 +299,11 @@ void write_aclip(int clipboard, char *, int, bool);
|
||||
* `lpstrFilter' in an OPENFILENAME structure.
|
||||
*/
|
||||
#define FILTER_KEY_FILES ("PuTTY Private Key Files (*.ppk)\0*.ppk\0" \
|
||||
"All Files (*.*)\0*\0\0\0")
|
||||
"All Files (*.*)\0*\0\0\0")
|
||||
#define FILTER_WAVE_FILES ("Wave Files (*.wav)\0*.WAV\0" \
|
||||
"All Files (*.*)\0*\0\0\0")
|
||||
"All Files (*.*)\0*\0\0\0")
|
||||
#define FILTER_DYNLIB_FILES ("Dynamic Library Files (*.dll)\0*.dll\0" \
|
||||
"All Files (*.*)\0*\0\0\0")
|
||||
"All Files (*.*)\0*\0\0\0")
|
||||
|
||||
/*
|
||||
* Exports from winnet.c.
|
||||
@ -327,12 +327,12 @@ SockAddr *sk_namedpipe_addr(const char *pipename);
|
||||
* here they are.
|
||||
*/
|
||||
DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAAsyncSelect,
|
||||
(SOCKET, HWND, u_int, long));
|
||||
(SOCKET, HWND, u_int, long));
|
||||
DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAEventSelect,
|
||||
(SOCKET, WSAEVENT, long));
|
||||
(SOCKET, WSAEVENT, long));
|
||||
DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAGetLastError, (void));
|
||||
DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAEnumNetworkEvents,
|
||||
(SOCKET, WSAEVENT, LPWSANETWORKEVENTS));
|
||||
(SOCKET, WSAEVENT, LPWSANETWORKEVENTS));
|
||||
#ifdef NEED_DECLARATION_OF_SELECT
|
||||
/* This declaration is protected by an ifdef for the sake of building
|
||||
* against winelib, in which you have to include winsock2.h before
|
||||
@ -342,8 +342,8 @@ DECL_WINDOWS_FUNCTION(GLOBAL, int, WSAEnumNetworkEvents,
|
||||
* this function pointer will see its declaration, and _those_ modules
|
||||
* - which will be Windows-specific anyway - can take more care. */
|
||||
DECL_WINDOWS_FUNCTION(GLOBAL, int, select,
|
||||
(int, fd_set FAR *, fd_set FAR *,
|
||||
fd_set FAR *, const struct timeval FAR *));
|
||||
(int, fd_set FAR *, fd_set FAR *,
|
||||
fd_set FAR *, const struct timeval FAR *));
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -402,21 +402,21 @@ struct prefslist {
|
||||
* parameter, and hence is passed back to winctrls access functions.
|
||||
*/
|
||||
struct dlgparam {
|
||||
HWND hwnd; /* the hwnd of the dialog box */
|
||||
HWND hwnd; /* the hwnd of the dialog box */
|
||||
struct winctrls *controltrees[8]; /* can have several of these */
|
||||
int nctrltrees;
|
||||
char *wintitle; /* title of actual window */
|
||||
char *errtitle; /* title of error sub-messageboxes */
|
||||
void *data; /* data to pass in refresh events */
|
||||
char *wintitle; /* title of actual window */
|
||||
char *errtitle; /* title of error sub-messageboxes */
|
||||
void *data; /* data to pass in refresh events */
|
||||
union control *focused, *lastfocused; /* which ctrl has focus now/before */
|
||||
bool shortcuts[128]; /* track which shortcuts in use */
|
||||
bool coloursel_wanted; /* has an event handler asked for
|
||||
* a colour selector? */
|
||||
* a colour selector? */
|
||||
struct {
|
||||
unsigned char r, g, b; /* 0-255 */
|
||||
bool ok;
|
||||
} coloursel_result;
|
||||
tree234 *privdata; /* stores per-control private data */
|
||||
tree234 *privdata; /* stores per-control private data */
|
||||
bool ended; /* has the dialog been ended? */
|
||||
int endresult; /* and if so, what was the result? */
|
||||
bool fixed_pitch_fonts; /* are we constrained to fixed fonts? */
|
||||
@ -426,57 +426,57 @@ struct dlgparam {
|
||||
* Exports from winctrls.c.
|
||||
*/
|
||||
void ctlposinit(struct ctlpos *cp, HWND hwnd,
|
||||
int leftborder, int rightborder, int topborder);
|
||||
int leftborder, int rightborder, int topborder);
|
||||
HWND doctl(struct ctlpos *cp, RECT r,
|
||||
char *wclass, int wstyle, int exstyle, char *wtext, int wid);
|
||||
char *wclass, int wstyle, int exstyle, char *wtext, int wid);
|
||||
void bartitle(struct ctlpos *cp, char *name, int id);
|
||||
void beginbox(struct ctlpos *cp, char *name, int idbox);
|
||||
void endbox(struct ctlpos *cp);
|
||||
void editboxfw(struct ctlpos *cp, bool password, char *text,
|
||||
int staticid, int editid);
|
||||
int staticid, int editid);
|
||||
void radioline(struct ctlpos *cp, char *text, int id, int nacross, ...);
|
||||
void bareradioline(struct ctlpos *cp, int nacross, ...);
|
||||
void radiobig(struct ctlpos *cp, char *text, int id, ...);
|
||||
void checkbox(struct ctlpos *cp, char *text, int id);
|
||||
void statictext(struct ctlpos *cp, char *text, int lines, int id);
|
||||
void staticbtn(struct ctlpos *cp, char *stext, int sid,
|
||||
char *btext, int bid);
|
||||
char *btext, int bid);
|
||||
void static2btn(struct ctlpos *cp, char *stext, int sid,
|
||||
char *btext1, int bid1, char *btext2, int bid2);
|
||||
char *btext1, int bid1, char *btext2, int bid2);
|
||||
void staticedit(struct ctlpos *cp, char *stext,
|
||||
int sid, int eid, int percentedit);
|
||||
int sid, int eid, int percentedit);
|
||||
void staticddl(struct ctlpos *cp, char *stext,
|
||||
int sid, int lid, int percentlist);
|
||||
int sid, int lid, int percentlist);
|
||||
void combobox(struct ctlpos *cp, char *text, int staticid, int listid);
|
||||
void staticpassedit(struct ctlpos *cp, char *stext,
|
||||
int sid, int eid, int percentedit);
|
||||
int sid, int eid, int percentedit);
|
||||
void bigeditctrl(struct ctlpos *cp, char *stext,
|
||||
int sid, int eid, int lines);
|
||||
int sid, int eid, int lines);
|
||||
void ersatztab(struct ctlpos *cp, char *stext, int sid, int lid, int s2id);
|
||||
void editbutton(struct ctlpos *cp, char *stext, int sid,
|
||||
int eid, char *btext, int bid);
|
||||
int eid, char *btext, int bid);
|
||||
void sesssaver(struct ctlpos *cp, char *text,
|
||||
int staticid, int editid, int listid, ...);
|
||||
int staticid, int editid, int listid, ...);
|
||||
void envsetter(struct ctlpos *cp, char *stext, int sid,
|
||||
char *e1stext, int e1sid, int e1id,
|
||||
char *e2stext, int e2sid, int e2id,
|
||||
int listid, char *b1text, int b1id, char *b2text, int b2id);
|
||||
char *e1stext, int e1sid, int e1id,
|
||||
char *e2stext, int e2sid, int e2id,
|
||||
int listid, char *b1text, int b1id, char *b2text, int b2id);
|
||||
void charclass(struct ctlpos *cp, char *stext, int sid, int listid,
|
||||
char *btext, int bid, int eid, char *s2text, int s2id);
|
||||
char *btext, int bid, int eid, char *s2text, int s2id);
|
||||
void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
|
||||
char *btext, int bid, ...);
|
||||
char *btext, int bid, ...);
|
||||
void prefslist(struct prefslist *hdl, struct ctlpos *cp, int lines,
|
||||
char *stext, int sid, int listid, int upbid, int dnbid);
|
||||
char *stext, int sid, int listid, int upbid, int dnbid);
|
||||
int handle_prefslist(struct prefslist *hdl,
|
||||
int *array, int maxmemb,
|
||||
bool is_dlmsg, HWND hwnd,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
int *array, int maxmemb,
|
||||
bool is_dlmsg, HWND hwnd,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
void progressbar(struct ctlpos *cp, int id);
|
||||
void fwdsetter(struct ctlpos *cp, int listid, char *stext, int sid,
|
||||
char *e1stext, int e1sid, int e1id,
|
||||
char *e2stext, int e2sid, int e2id,
|
||||
char *btext, int bid,
|
||||
char *r1text, int r1id, char *r2text, int r2id);
|
||||
char *e1stext, int e1sid, int e1id,
|
||||
char *e2stext, int e2sid, int e2id,
|
||||
char *btext, int bid,
|
||||
char *r1text, int r1id, char *r2text, int r2id);
|
||||
|
||||
void dlg_auto_set_fixed_pitch_flag(dlgparam *dlg);
|
||||
bool dlg_get_fixed_pitch_flag(dlgparam *dlg);
|
||||
@ -531,7 +531,7 @@ struct winctrl *winctrl_findbyctrl(struct winctrls *, union control *);
|
||||
struct winctrl *winctrl_findbyid(struct winctrls *, int);
|
||||
struct winctrl *winctrl_findbyindex(struct winctrls *, int);
|
||||
void winctrl_layout(struct dlgparam *dp, struct winctrls *wc,
|
||||
struct ctlpos *cp, struct controlset *s, int *id);
|
||||
struct ctlpos *cp, struct controlset *s, int *id);
|
||||
bool winctrl_handle_command(struct dlgparam *dp, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
void winctrl_rem_shortcuts(struct dlgparam *dp, struct winctrl *c);
|
||||
@ -545,7 +545,7 @@ void dp_cleanup(struct dlgparam *dp);
|
||||
* Exports from wincfg.c.
|
||||
*/
|
||||
void win_setup_config_box(struct controlbox *b, HWND *hwndp, bool has_help,
|
||||
bool midsession, int protocol);
|
||||
bool midsession, int protocol);
|
||||
|
||||
/*
|
||||
* Exports from windlg.c.
|
||||
@ -614,9 +614,9 @@ typedef size_t (*handle_inputfn_t)(
|
||||
typedef void (*handle_outputfn_t)(
|
||||
struct handle *h, size_t new_backlog, int err);
|
||||
struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
|
||||
void *privdata, int flags);
|
||||
void *privdata, int flags);
|
||||
struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
|
||||
void *privdata, int flags);
|
||||
void *privdata, int flags);
|
||||
size_t handle_write(struct handle *h, const void *data, size_t len);
|
||||
void handle_write_eof(struct handle *h);
|
||||
HANDLE *handle_get_events(int *nevents);
|
||||
@ -638,12 +638,12 @@ void handle_sink_init(handle_sink *sink, struct handle *h);
|
||||
* winpgntc.c needs to schedule callbacks for asynchronous agent
|
||||
* requests. This has to be done differently in GUI and console, so
|
||||
* there's an exported function used for the purpose.
|
||||
*
|
||||
*
|
||||
* Also, we supply FLAG_SYNCAGENT to force agent requests to be
|
||||
* synchronous in pscp and psftp.
|
||||
*/
|
||||
void agent_schedule_callback(void (*callback)(void *, void *, int),
|
||||
void *callback_ctx, void *data, int len);
|
||||
void *callback_ctx, void *data, int len);
|
||||
#define FLAG_SYNCAGENT 0x1000
|
||||
|
||||
/*
|
||||
|
352
windows/winucs.c
352
windows/winucs.c
@ -25,7 +25,7 @@ static const WCHAR unitab_xterm_std[32] = {
|
||||
* duplicate definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* Tables for ISO-8859-{1-10,13-16} derived from those downloaded
|
||||
* 2001-10-02 from <http://www.unicode.org/Public/MAPPINGS/> -- jtn
|
||||
* Table for ISO-8859-11 derived from same on 2002-11-18. -- bjh21
|
||||
@ -445,62 +445,62 @@ void init_ucs(Conf *conf, struct unicode_data *ucsdata)
|
||||
|
||||
/* Decide on the Line and Font codepages */
|
||||
ucsdata->line_codepage = decode_codepage(conf_get_str(conf,
|
||||
CONF_line_codepage));
|
||||
CONF_line_codepage));
|
||||
|
||||
if (ucsdata->font_codepage <= 0) {
|
||||
ucsdata->font_codepage=0;
|
||||
ucsdata->dbcs_screenfont=false;
|
||||
if (ucsdata->font_codepage <= 0) {
|
||||
ucsdata->font_codepage=0;
|
||||
ucsdata->dbcs_screenfont=false;
|
||||
}
|
||||
|
||||
vtmode = conf_get_int(conf, CONF_vtmode);
|
||||
if (vtmode == VT_OEMONLY) {
|
||||
ucsdata->font_codepage = 437;
|
||||
ucsdata->dbcs_screenfont = false;
|
||||
if (ucsdata->line_codepage <= 0)
|
||||
ucsdata->line_codepage = GetACP();
|
||||
ucsdata->font_codepage = 437;
|
||||
ucsdata->dbcs_screenfont = false;
|
||||
if (ucsdata->line_codepage <= 0)
|
||||
ucsdata->line_codepage = GetACP();
|
||||
} else if (ucsdata->line_codepage <= 0)
|
||||
ucsdata->line_codepage = ucsdata->font_codepage;
|
||||
ucsdata->line_codepage = ucsdata->font_codepage;
|
||||
|
||||
/* Collect screen font ucs table */
|
||||
if (ucsdata->dbcs_screenfont || ucsdata->font_codepage == 0) {
|
||||
get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 2);
|
||||
for (i = 128; i < 256; i++)
|
||||
ucsdata->unitab_font[i] = (WCHAR) (CSET_ACP + i);
|
||||
get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 2);
|
||||
for (i = 128; i < 256; i++)
|
||||
ucsdata->unitab_font[i] = (WCHAR) (CSET_ACP + i);
|
||||
} else {
|
||||
get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 1);
|
||||
get_unitab(ucsdata->font_codepage, ucsdata->unitab_font, 1);
|
||||
|
||||
/* CP437 fonts are often broken ... */
|
||||
if (ucsdata->font_codepage == 437)
|
||||
ucsdata->unitab_font[0] = ucsdata->unitab_font[255] = 0xFFFF;
|
||||
/* CP437 fonts are often broken ... */
|
||||
if (ucsdata->font_codepage == 437)
|
||||
ucsdata->unitab_font[0] = ucsdata->unitab_font[255] = 0xFFFF;
|
||||
}
|
||||
if (vtmode == VT_XWINDOWS)
|
||||
memcpy(ucsdata->unitab_font + 1, unitab_xterm_std,
|
||||
sizeof(unitab_xterm_std));
|
||||
memcpy(ucsdata->unitab_font + 1, unitab_xterm_std,
|
||||
sizeof(unitab_xterm_std));
|
||||
|
||||
/* Collect OEMCP ucs table */
|
||||
get_unitab(CP_OEMCP, ucsdata->unitab_oemcp, 1);
|
||||
|
||||
/* Collect CP437 ucs table for SCO acs */
|
||||
if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS)
|
||||
memcpy(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp,
|
||||
sizeof(ucsdata->unitab_scoacs));
|
||||
memcpy(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp,
|
||||
sizeof(ucsdata->unitab_scoacs));
|
||||
else
|
||||
get_unitab(437, ucsdata->unitab_scoacs, 1);
|
||||
get_unitab(437, ucsdata->unitab_scoacs, 1);
|
||||
|
||||
/* Collect line set ucs table */
|
||||
if (ucsdata->line_codepage == ucsdata->font_codepage &&
|
||||
(ucsdata->dbcs_screenfont ||
|
||||
vtmode == VT_POORMAN || ucsdata->font_codepage==0)) {
|
||||
(ucsdata->dbcs_screenfont ||
|
||||
vtmode == VT_POORMAN || ucsdata->font_codepage==0)) {
|
||||
|
||||
/* For DBCS and POOR fonts force direct to font */
|
||||
used_dtf = true;
|
||||
for (i = 0; i < 32; i++)
|
||||
ucsdata->unitab_line[i] = (WCHAR) i;
|
||||
for (i = 32; i < 256; i++)
|
||||
ucsdata->unitab_line[i] = (WCHAR) (CSET_ACP + i);
|
||||
ucsdata->unitab_line[127] = (WCHAR) 127;
|
||||
/* For DBCS and POOR fonts force direct to font */
|
||||
used_dtf = true;
|
||||
for (i = 0; i < 32; i++)
|
||||
ucsdata->unitab_line[i] = (WCHAR) i;
|
||||
for (i = 32; i < 256; i++)
|
||||
ucsdata->unitab_line[i] = (WCHAR) (CSET_ACP + i);
|
||||
ucsdata->unitab_line[127] = (WCHAR) 127;
|
||||
} else {
|
||||
get_unitab(ucsdata->line_codepage, ucsdata->unitab_line, 0);
|
||||
get_unitab(ucsdata->line_codepage, ucsdata->unitab_line, 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -508,101 +508,101 @@ void init_ucs(Conf *conf, struct unicode_data *ucsdata)
|
||||
ucsdata->font_codepage, ucsdata->dbcs_screenfont ? " DBCS" : "");
|
||||
|
||||
for (i = 0; i < 256; i += 16) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
debug("%04x%s", ucsdata->unitab_line[i + j], j == 15 ? "" : ",");
|
||||
}
|
||||
debug("\n");
|
||||
for (j = 0; j < 16; j++) {
|
||||
debug("%04x%s", ucsdata->unitab_line[i + j], j == 15 ? "" : ",");
|
||||
}
|
||||
debug("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* VT100 graphics - NB: Broken for non-ascii CP's */
|
||||
memcpy(ucsdata->unitab_xterm, ucsdata->unitab_line,
|
||||
sizeof(ucsdata->unitab_xterm));
|
||||
sizeof(ucsdata->unitab_xterm));
|
||||
memcpy(ucsdata->unitab_xterm + '`', unitab_xterm_std,
|
||||
sizeof(unitab_xterm_std));
|
||||
sizeof(unitab_xterm_std));
|
||||
ucsdata->unitab_xterm['_'] = ' ';
|
||||
|
||||
/* Generate UCS ->line page table. */
|
||||
if (ucsdata->uni_tbl) {
|
||||
for (i = 0; i < 256; i++)
|
||||
if (ucsdata->uni_tbl[i])
|
||||
sfree(ucsdata->uni_tbl[i]);
|
||||
sfree(ucsdata->uni_tbl);
|
||||
ucsdata->uni_tbl = 0;
|
||||
for (i = 0; i < 256; i++)
|
||||
if (ucsdata->uni_tbl[i])
|
||||
sfree(ucsdata->uni_tbl[i]);
|
||||
sfree(ucsdata->uni_tbl);
|
||||
ucsdata->uni_tbl = 0;
|
||||
}
|
||||
if (!used_dtf) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (DIRECT_CHAR(ucsdata->unitab_line[i]))
|
||||
continue;
|
||||
if (DIRECT_FONT(ucsdata->unitab_line[i]))
|
||||
continue;
|
||||
if (!ucsdata->uni_tbl) {
|
||||
ucsdata->uni_tbl = snewn(256, char *);
|
||||
memset(ucsdata->uni_tbl, 0, 256 * sizeof(char *));
|
||||
}
|
||||
j = ((ucsdata->unitab_line[i] >> 8) & 0xFF);
|
||||
if (!ucsdata->uni_tbl[j]) {
|
||||
ucsdata->uni_tbl[j] = snewn(256, char);
|
||||
memset(ucsdata->uni_tbl[j], 0, 256 * sizeof(char));
|
||||
}
|
||||
ucsdata->uni_tbl[j][ucsdata->unitab_line[i] & 0xFF] = i;
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (DIRECT_CHAR(ucsdata->unitab_line[i]))
|
||||
continue;
|
||||
if (DIRECT_FONT(ucsdata->unitab_line[i]))
|
||||
continue;
|
||||
if (!ucsdata->uni_tbl) {
|
||||
ucsdata->uni_tbl = snewn(256, char *);
|
||||
memset(ucsdata->uni_tbl, 0, 256 * sizeof(char *));
|
||||
}
|
||||
j = ((ucsdata->unitab_line[i] >> 8) & 0xFF);
|
||||
if (!ucsdata->uni_tbl[j]) {
|
||||
ucsdata->uni_tbl[j] = snewn(256, char);
|
||||
memset(ucsdata->uni_tbl[j], 0, 256 * sizeof(char));
|
||||
}
|
||||
ucsdata->uni_tbl[j][ucsdata->unitab_line[i] & 0xFF] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the line control characters. */
|
||||
for (i = 0; i < 256; i++)
|
||||
if (ucsdata->unitab_line[i] < ' '
|
||||
|| (ucsdata->unitab_line[i] >= 0x7F &&
|
||||
ucsdata->unitab_line[i] < 0xA0))
|
||||
ucsdata->unitab_ctrl[i] = i;
|
||||
else
|
||||
ucsdata->unitab_ctrl[i] = 0xFF;
|
||||
if (ucsdata->unitab_line[i] < ' '
|
||||
|| (ucsdata->unitab_line[i] >= 0x7F &&
|
||||
ucsdata->unitab_line[i] < 0xA0))
|
||||
ucsdata->unitab_ctrl[i] = i;
|
||||
else
|
||||
ucsdata->unitab_ctrl[i] = 0xFF;
|
||||
|
||||
/* Generate line->screen direct conversion links. */
|
||||
if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS)
|
||||
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp, CSET_OEMCP);
|
||||
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_oemcp, CSET_OEMCP);
|
||||
|
||||
link_font(ucsdata->unitab_line, ucsdata->unitab_font, CSET_ACP);
|
||||
link_font(ucsdata->unitab_scoacs, ucsdata->unitab_font, CSET_ACP);
|
||||
link_font(ucsdata->unitab_xterm, ucsdata->unitab_font, CSET_ACP);
|
||||
|
||||
if (vtmode == VT_OEMANSI || vtmode == VT_XWINDOWS) {
|
||||
link_font(ucsdata->unitab_line, ucsdata->unitab_oemcp, CSET_OEMCP);
|
||||
link_font(ucsdata->unitab_xterm, ucsdata->unitab_oemcp, CSET_OEMCP);
|
||||
link_font(ucsdata->unitab_line, ucsdata->unitab_oemcp, CSET_OEMCP);
|
||||
link_font(ucsdata->unitab_xterm, ucsdata->unitab_oemcp, CSET_OEMCP);
|
||||
}
|
||||
|
||||
if (ucsdata->dbcs_screenfont &&
|
||||
ucsdata->font_codepage != ucsdata->line_codepage) {
|
||||
/* F***ing Microsoft fonts, Japanese and Korean codepage fonts
|
||||
* have a currency symbol at 0x5C but their unicode value is
|
||||
* still given as U+005C not the correct U+00A5. */
|
||||
ucsdata->unitab_line['\\'] = CSET_OEMCP + '\\';
|
||||
ucsdata->font_codepage != ucsdata->line_codepage) {
|
||||
/* F***ing Microsoft fonts, Japanese and Korean codepage fonts
|
||||
* have a currency symbol at 0x5C but their unicode value is
|
||||
* still given as U+005C not the correct U+00A5. */
|
||||
ucsdata->unitab_line['\\'] = CSET_OEMCP + '\\';
|
||||
}
|
||||
|
||||
/* Last chance, if !unicode then try poorman links. */
|
||||
if (vtmode != VT_UNICODE) {
|
||||
static const char poorman_scoacs[] =
|
||||
"CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
|
||||
static const char poorman_latin1[] =
|
||||
" !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
|
||||
static const char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
|
||||
static const char poorman_scoacs[] =
|
||||
"CueaaaaceeeiiiAAE**ooouuyOUc$YPsaiounNao?++**!<>###||||++||++++++--|-+||++--|-+----++++++++##||#aBTPEsyt******EN=+><++-=... n2* ";
|
||||
static const char poorman_latin1[] =
|
||||
" !cL.Y|S\"Ca<--R~o+23'u|.,1o>///?AAAAAAACEEEEIIIIDNOOOOOxOUUUUYPBaaaaaaaceeeeiiiionooooo/ouuuuypy";
|
||||
static const char poorman_vt100[] = "*#****o~**+++++-----++++|****L.";
|
||||
|
||||
for (i = 160; i < 256; i++)
|
||||
if (!DIRECT_FONT(ucsdata->unitab_line[i]) &&
|
||||
ucsdata->unitab_line[i] >= 160 &&
|
||||
ucsdata->unitab_line[i] < 256) {
|
||||
ucsdata->unitab_line[i] =
|
||||
(WCHAR) (CSET_ACP +
|
||||
poorman_latin1[ucsdata->unitab_line[i] - 160]);
|
||||
}
|
||||
for (i = 96; i < 127; i++)
|
||||
if (!DIRECT_FONT(ucsdata->unitab_xterm[i]))
|
||||
ucsdata->unitab_xterm[i] =
|
||||
(WCHAR) (CSET_ACP + poorman_vt100[i - 96]);
|
||||
for(i=128;i<256;i++)
|
||||
if (!DIRECT_FONT(ucsdata->unitab_scoacs[i]))
|
||||
ucsdata->unitab_scoacs[i] =
|
||||
(WCHAR) (CSET_ACP + poorman_scoacs[i - 128]);
|
||||
for (i = 160; i < 256; i++)
|
||||
if (!DIRECT_FONT(ucsdata->unitab_line[i]) &&
|
||||
ucsdata->unitab_line[i] >= 160 &&
|
||||
ucsdata->unitab_line[i] < 256) {
|
||||
ucsdata->unitab_line[i] =
|
||||
(WCHAR) (CSET_ACP +
|
||||
poorman_latin1[ucsdata->unitab_line[i] - 160]);
|
||||
}
|
||||
for (i = 96; i < 127; i++)
|
||||
if (!DIRECT_FONT(ucsdata->unitab_xterm[i]))
|
||||
ucsdata->unitab_xterm[i] =
|
||||
(WCHAR) (CSET_ACP + poorman_vt100[i - 96]);
|
||||
for(i=128;i<256;i++)
|
||||
if (!DIRECT_FONT(ucsdata->unitab_scoacs[i]))
|
||||
ucsdata->unitab_scoacs[i] =
|
||||
(WCHAR) (CSET_ACP + poorman_scoacs[i - 128]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -610,15 +610,15 @@ static void link_font(WCHAR * line_tbl, WCHAR * font_tbl, WCHAR attr)
|
||||
{
|
||||
int font_index, line_index, i;
|
||||
for (line_index = 0; line_index < 256; line_index++) {
|
||||
if (DIRECT_FONT(line_tbl[line_index]))
|
||||
continue;
|
||||
for(i = 0; i < 256; i++) {
|
||||
font_index = ((32 + i) & 0xFF);
|
||||
if (line_tbl[line_index] == font_tbl[font_index]) {
|
||||
line_tbl[line_index] = (WCHAR) (attr + font_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (DIRECT_FONT(line_tbl[line_index]))
|
||||
continue;
|
||||
for(i = 0; i < 256; i++) {
|
||||
font_index = ((32 + i) & 0xFF);
|
||||
if (line_tbl[line_index] == font_tbl[font_index]) {
|
||||
line_tbl[line_index] = (WCHAR) (attr + font_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -649,7 +649,7 @@ int check_compose_internal(int first, int second, int recurse)
|
||||
{
|
||||
|
||||
static const struct {
|
||||
char first, second;
|
||||
char first, second;
|
||||
wchar_t composed;
|
||||
} composetbl[] = {
|
||||
{0x2b, 0x2b, 0x0023},
|
||||
@ -981,16 +981,16 @@ int check_compose_internal(int first, int second, int recurse)
|
||||
int nc = -1;
|
||||
|
||||
for (c = composetbl; c->first; c++) {
|
||||
if (c->first == first && c->second == second)
|
||||
return c->composed;
|
||||
if (c->first == first && c->second == second)
|
||||
return c->composed;
|
||||
}
|
||||
|
||||
if (recurse == 0) {
|
||||
nc = check_compose_internal(second, first, 1);
|
||||
if (nc == -1)
|
||||
nc = check_compose_internal(toupper(first), toupper(second), 1);
|
||||
if (nc == -1)
|
||||
nc = check_compose_internal(toupper(second), toupper(first), 1);
|
||||
nc = check_compose_internal(second, first, 1);
|
||||
if (nc == -1)
|
||||
nc = check_compose_internal(toupper(first), toupper(second), 1);
|
||||
if (nc == -1)
|
||||
nc = check_compose_internal(toupper(second), toupper(first), 1);
|
||||
}
|
||||
return nc;
|
||||
}
|
||||
@ -1047,7 +1047,7 @@ int decode_codepage(char *cp_name)
|
||||
d += 3;
|
||||
for (s = d; *s >= '0' && *s <= '9'; s++);
|
||||
if (*s == 0 && s != d)
|
||||
codepage = atoi(d); /* CP999 or IBM999 */
|
||||
codepage = atoi(d); /* CP999 or IBM999 */
|
||||
|
||||
if (codepage == CP_ACP)
|
||||
codepage = GetACP();
|
||||
@ -1058,15 +1058,15 @@ int decode_codepage(char *cp_name)
|
||||
|
||||
break_break:;
|
||||
if (codepage != -1) {
|
||||
if (codepage != CP_UTF8 && codepage < 65536) {
|
||||
if (GetCPInfo(codepage, &cpinfo) == 0) {
|
||||
codepage = -2;
|
||||
} else if (cpinfo.MaxCharSize > 1)
|
||||
codepage = -3;
|
||||
}
|
||||
if (codepage != CP_UTF8 && codepage < 65536) {
|
||||
if (GetCPInfo(codepage, &cpinfo) == 0) {
|
||||
codepage = -2;
|
||||
} else if (cpinfo.MaxCharSize > 1)
|
||||
codepage = -3;
|
||||
}
|
||||
}
|
||||
if (codepage == -1 && *cp_name)
|
||||
codepage = -2;
|
||||
codepage = -2;
|
||||
return codepage;
|
||||
}
|
||||
|
||||
@ -1076,32 +1076,32 @@ const char *cp_name(int codepage)
|
||||
static char buf[32];
|
||||
|
||||
if (codepage == -1) {
|
||||
sprintf(buf, "Use font encoding");
|
||||
return buf;
|
||||
sprintf(buf, "Use font encoding");
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (codepage > 0 && codepage < 65536)
|
||||
sprintf(buf, "CP%03d", codepage);
|
||||
sprintf(buf, "CP%03d", codepage);
|
||||
else
|
||||
*buf = 0;
|
||||
*buf = 0;
|
||||
|
||||
if (codepage >= 65536) {
|
||||
cpno = 0;
|
||||
for (cpi = cp_list; cpi->name; cpi++)
|
||||
if (cpi == cp_list + (codepage - 65536)) {
|
||||
cpno = cpi;
|
||||
break;
|
||||
}
|
||||
if (cpno)
|
||||
for (cpi = cp_list; cpi->name; cpi++) {
|
||||
if (cpno->cp_table == cpi->cp_table)
|
||||
return cpi->name;
|
||||
}
|
||||
cpno = 0;
|
||||
for (cpi = cp_list; cpi->name; cpi++)
|
||||
if (cpi == cp_list + (codepage - 65536)) {
|
||||
cpno = cpi;
|
||||
break;
|
||||
}
|
||||
if (cpno)
|
||||
for (cpi = cp_list; cpi->name; cpi++) {
|
||||
if (cpno->cp_table == cpi->cp_table)
|
||||
return cpi->name;
|
||||
}
|
||||
} else {
|
||||
for (cpi = cp_list; cpi->name; cpi++) {
|
||||
if (codepage == cpi->codepage)
|
||||
return cpi->name;
|
||||
}
|
||||
for (cpi = cp_list; cpi->name; cpi++) {
|
||||
if (codepage == cpi->codepage)
|
||||
return cpi->name;
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
@ -1113,7 +1113,7 @@ const char *cp_name(int codepage)
|
||||
const char *cp_enumerate(int index)
|
||||
{
|
||||
if (index < 0 || index >= lenof(cp_list))
|
||||
return NULL;
|
||||
return NULL;
|
||||
return cp_list[index].name;
|
||||
}
|
||||
|
||||
@ -1123,53 +1123,53 @@ void get_unitab(int codepage, wchar_t * unitab, int ftype)
|
||||
int i, max = 256, flg = MB_ERR_INVALID_CHARS;
|
||||
|
||||
if (ftype)
|
||||
flg |= MB_USEGLYPHCHARS;
|
||||
flg |= MB_USEGLYPHCHARS;
|
||||
if (ftype == 2)
|
||||
max = 128;
|
||||
max = 128;
|
||||
|
||||
if (codepage == CP_UTF8) {
|
||||
for (i = 0; i < max; i++)
|
||||
unitab[i] = i;
|
||||
return;
|
||||
for (i = 0; i < max; i++)
|
||||
unitab[i] = i;
|
||||
return;
|
||||
}
|
||||
|
||||
if (codepage == CP_ACP)
|
||||
codepage = GetACP();
|
||||
codepage = GetACP();
|
||||
else if (codepage == CP_OEMCP)
|
||||
codepage = GetOEMCP();
|
||||
codepage = GetOEMCP();
|
||||
|
||||
if (codepage > 0 && codepage < 65536) {
|
||||
for (i = 0; i < max; i++) {
|
||||
tbuf[0] = i;
|
||||
for (i = 0; i < max; i++) {
|
||||
tbuf[0] = i;
|
||||
|
||||
if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
|
||||
!= 1)
|
||||
unitab[i] = 0xFFFD;
|
||||
}
|
||||
if (mb_to_wc(codepage, flg, tbuf, 1, unitab + i, 1)
|
||||
!= 1)
|
||||
unitab[i] = 0xFFFD;
|
||||
}
|
||||
} else {
|
||||
int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
|
||||
for (i = 0; i < max; i++)
|
||||
unitab[i] = i;
|
||||
for (i = j; i < max; i++)
|
||||
unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
|
||||
int j = 256 - cp_list[codepage & 0xFFFF].cp_size;
|
||||
for (i = 0; i < max; i++)
|
||||
unitab[i] = i;
|
||||
for (i = j; i < max; i++)
|
||||
unitab[i] = cp_list[codepage & 0xFFFF].cp_table[i - j];
|
||||
}
|
||||
}
|
||||
|
||||
int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
|
||||
char *mbstr, int mblen, const char *defchr,
|
||||
struct unicode_data *ucsdata)
|
||||
char *mbstr, int mblen, const char *defchr,
|
||||
struct unicode_data *ucsdata)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
if (ucsdata && codepage == ucsdata->line_codepage && ucsdata->uni_tbl) {
|
||||
/* Do this by array lookup if we can. */
|
||||
if (wclen < 0) {
|
||||
for (wclen = 0; wcstr[wclen++] ;); /* will include the NUL */
|
||||
}
|
||||
for (p = mbstr, i = 0; i < wclen; i++) {
|
||||
wchar_t ch = wcstr[i];
|
||||
int by;
|
||||
char *p1;
|
||||
/* Do this by array lookup if we can. */
|
||||
if (wclen < 0) {
|
||||
for (wclen = 0; wcstr[wclen++] ;); /* will include the NUL */
|
||||
}
|
||||
for (p = mbstr, i = 0; i < wclen; i++) {
|
||||
wchar_t ch = wcstr[i];
|
||||
int by;
|
||||
char *p1;
|
||||
|
||||
#define WRITECH(chr) do \
|
||||
{ \
|
||||
@ -1179,30 +1179,30 @@ int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
|
||||
|
||||
if (ucsdata->uni_tbl &&
|
||||
(p1 = ucsdata->uni_tbl[(ch >> 8) & 0xFF]) != NULL &&
|
||||
(by = p1[ch & 0xFF]) != '\0')
|
||||
(by = p1[ch & 0xFF]) != '\0')
|
||||
WRITECH(by);
|
||||
else if (ch < 0x80)
|
||||
else if (ch < 0x80)
|
||||
WRITECH(ch);
|
||||
else if (defchr)
|
||||
for (const char *q = defchr; *q; q++)
|
||||
WRITECH(*q);
|
||||
#if 1
|
||||
else
|
||||
WRITECH('.');
|
||||
else
|
||||
WRITECH('.');
|
||||
#endif
|
||||
|
||||
#undef WRITECH
|
||||
}
|
||||
return p - mbstr;
|
||||
}
|
||||
return p - mbstr;
|
||||
} else {
|
||||
int defused;
|
||||
return WideCharToMultiByte(codepage, flags, wcstr, wclen,
|
||||
mbstr, mblen, defchr, &defused);
|
||||
return WideCharToMultiByte(codepage, flags, wcstr, wclen,
|
||||
mbstr, mblen, defchr, &defused);
|
||||
}
|
||||
}
|
||||
|
||||
int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,
|
||||
wchar_t *wcstr, int wclen)
|
||||
wchar_t *wcstr, int wclen)
|
||||
{
|
||||
return MultiByteToWideChar(codepage, flags, mbstr, mblen, wcstr, wclen);
|
||||
}
|
||||
|
@ -41,36 +41,36 @@ bool request_file(filereq *state, OPENFILENAME *of, bool preserve, bool save)
|
||||
|
||||
/* Get process CWD */
|
||||
if (preserve) {
|
||||
DWORD r = GetCurrentDirectory(lenof(cwd), cwd);
|
||||
if (r == 0 || r >= lenof(cwd))
|
||||
/* Didn't work, oh well. Stop trying to be clever. */
|
||||
preserve = false;
|
||||
DWORD r = GetCurrentDirectory(lenof(cwd), cwd);
|
||||
if (r == 0 || r >= lenof(cwd))
|
||||
/* Didn't work, oh well. Stop trying to be clever. */
|
||||
preserve = false;
|
||||
}
|
||||
|
||||
/* Open the file requester, maybe setting lpstrInitialDir */
|
||||
{
|
||||
#ifdef OPENFILENAME_SIZE_VERSION_400
|
||||
of->lStructSize = OPENFILENAME_SIZE_VERSION_400;
|
||||
of->lStructSize = OPENFILENAME_SIZE_VERSION_400;
|
||||
#else
|
||||
of->lStructSize = sizeof(*of);
|
||||
of->lStructSize = sizeof(*of);
|
||||
#endif
|
||||
of->lpstrInitialDir = (state && state->cwd[0]) ? state->cwd : NULL;
|
||||
/* Actually put up the requester. */
|
||||
ret = save ? GetSaveFileName(of) : GetOpenFileName(of);
|
||||
of->lpstrInitialDir = (state && state->cwd[0]) ? state->cwd : NULL;
|
||||
/* Actually put up the requester. */
|
||||
ret = save ? GetSaveFileName(of) : GetOpenFileName(of);
|
||||
}
|
||||
|
||||
/* Get CWD left by requester */
|
||||
if (state) {
|
||||
DWORD r = GetCurrentDirectory(lenof(state->cwd), state->cwd);
|
||||
if (r == 0 || r >= lenof(state->cwd))
|
||||
/* Didn't work, oh well. */
|
||||
state->cwd[0] = '\0';
|
||||
DWORD r = GetCurrentDirectory(lenof(state->cwd), state->cwd);
|
||||
if (r == 0 || r >= lenof(state->cwd))
|
||||
/* Didn't work, oh well. */
|
||||
state->cwd[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
/* Restore process CWD */
|
||||
if (preserve)
|
||||
/* If it fails, there's not much we can do. */
|
||||
(void) SetCurrentDirectory(cwd);
|
||||
/* If it fails, there's not much we can do. */
|
||||
(void) SetCurrentDirectory(cwd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -97,8 +97,8 @@ static VOID CALLBACK message_box_help_callback(LPHELPINFO lpHelpInfo)
|
||||
const char *context = NULL;
|
||||
#define CHECK_CTX(name) \
|
||||
do { \
|
||||
if (lpHelpInfo->dwContextId == WINHELP_CTXID_ ## name) \
|
||||
context = WINHELP_CTX_ ## name; \
|
||||
if (lpHelpInfo->dwContextId == WINHELP_CTXID_ ## name) \
|
||||
context = WINHELP_CTX_ ## name; \
|
||||
} while (0)
|
||||
CHECK_CTX(errors_hostkey_absent);
|
||||
CHECK_CTX(errors_hostkey_changed);
|
||||
@ -107,13 +107,13 @@ static VOID CALLBACK message_box_help_callback(LPHELPINFO lpHelpInfo)
|
||||
CHECK_CTX(pgp_fingerprints);
|
||||
#undef CHECK_CTX
|
||||
if (context)
|
||||
launch_help(hwnd, context);
|
||||
launch_help(hwnd, context);
|
||||
}
|
||||
|
||||
int message_box(LPCTSTR text, LPCTSTR caption, DWORD style, DWORD helpctxid)
|
||||
{
|
||||
MSGBOXPARAMS mbox;
|
||||
|
||||
|
||||
/*
|
||||
* We use MessageBoxIndirect() because it allows us to specify a
|
||||
* callback function for the Help button.
|
||||
@ -138,18 +138,18 @@ int message_box(LPCTSTR text, LPCTSTR caption, DWORD style, DWORD helpctxid)
|
||||
void pgp_fingerprints(void)
|
||||
{
|
||||
message_box("These are the fingerprints of the PuTTY PGP Master Keys. They can\n"
|
||||
"be used to establish a trust path from this executable to another\n"
|
||||
"one. See the manual for more information.\n"
|
||||
"(Note: these fingerprints have nothing to do with SSH!)\n"
|
||||
"\n"
|
||||
"be used to establish a trust path from this executable to another\n"
|
||||
"one. See the manual for more information.\n"
|
||||
"(Note: these fingerprints have nothing to do with SSH!)\n"
|
||||
"\n"
|
||||
"PuTTY Master Key as of " PGP_MASTER_KEY_YEAR
|
||||
" (" PGP_MASTER_KEY_DETAILS "):\n"
|
||||
" " PGP_MASTER_KEY_FP "\n\n"
|
||||
"Previous Master Key (" PGP_PREV_MASTER_KEY_YEAR
|
||||
", " PGP_PREV_MASTER_KEY_DETAILS "):\n"
|
||||
" " PGP_PREV_MASTER_KEY_FP,
|
||||
"PGP fingerprints", MB_ICONINFORMATION | MB_OK,
|
||||
HELPCTXID(pgp_fingerprints));
|
||||
"PGP fingerprints", MB_ICONINFORMATION | MB_OK,
|
||||
HELPCTXID(pgp_fingerprints));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -164,7 +164,7 @@ char *GetDlgItemText_alloc(HWND hwnd, int id)
|
||||
|
||||
do {
|
||||
sgrowarray_nm(ret, size, size);
|
||||
GetDlgItemText(hwnd, id, ret, size);
|
||||
GetDlgItemText(hwnd, id, ret, size);
|
||||
} while (!memchr(ret, '\0', size-1));
|
||||
|
||||
return ret;
|
||||
@ -177,9 +177,9 @@ char *GetDlgItemText_alloc(HWND hwnd, int id)
|
||||
* broken apart by the C library, will have their command lines
|
||||
* processed in the same way as the GUI utilities which get a whole
|
||||
* command line and must call this function).
|
||||
*
|
||||
*
|
||||
* Does not modify the input command line.
|
||||
*
|
||||
*
|
||||
* The final parameter (argstart) is used to return a second array
|
||||
* of char * pointers, the same length as argv, each one pointing
|
||||
* at the start of the corresponding element of argv in the
|
||||
@ -189,7 +189,7 @@ char *GetDlgItemText_alloc(HWND hwnd, int id)
|
||||
* `argstart' can be safely left NULL.
|
||||
*/
|
||||
void split_into_argv(char *cmdline, int *argc, char ***argv,
|
||||
char ***argstart)
|
||||
char ***argstart)
|
||||
{
|
||||
char *p;
|
||||
char *outputline, *q;
|
||||
@ -237,11 +237,11 @@ void split_into_argv(char *cmdline, int *argc, char ***argv,
|
||||
* quotes (down the left), and indicate how many backslashes
|
||||
* are output, how many quotes are output, and whether a
|
||||
* quoted segment is open at the end of the sequence:
|
||||
*
|
||||
*
|
||||
* backslashes
|
||||
*
|
||||
*
|
||||
* 0 1 2 3 4
|
||||
*
|
||||
*
|
||||
* 0 0,0,y | 1,0,y 2,0,y 3,0,y 4,0,y
|
||||
* --------+-----------------------------
|
||||
* 1 0,0,n | 0,1,y 1,0,n 1,1,y 2,0,n
|
||||
@ -255,18 +255,18 @@ void split_into_argv(char *cmdline, int *argc, char ***argv,
|
||||
* 9 0,3,y | 0,4,n 1,3,y 1,4,n 2,3,y
|
||||
* 10 0,3,n | 0,4,y 1,3,n 1,4,y 2,3,n
|
||||
* 11 0,4,n | 0,4,n 1,4,n 1,4,n 2,4,n
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* [Test fragment was of the form "a\\\"""b c" d.]
|
||||
*
|
||||
*
|
||||
* There is very weird mod-3 behaviour going on here in the
|
||||
* number of quotes, and it even applies when there aren't any
|
||||
* backslashes! How ghastly.
|
||||
*
|
||||
*
|
||||
* With a bit of thought, this extremely odd diagram suddenly
|
||||
* coalesced itself into a coherent, if still ghastly, model of
|
||||
* how things work:
|
||||
*
|
||||
*
|
||||
* - As before, backslashes are only special when one or more
|
||||
* of them appear contiguously before at least one double
|
||||
* quote. In this situation the backslashes do exactly what
|
||||
@ -275,17 +275,17 @@ void split_into_argv(char *cmdline, int *argc, char ***argv,
|
||||
* even) or (n-1)/2 literal backslashes and a literal quote
|
||||
* (if n is odd). In the latter case the double quote
|
||||
* character right after the backslashes is used up.
|
||||
*
|
||||
*
|
||||
* - After that, any remaining double quotes are processed. A
|
||||
* string of contiguous unescaped double quotes has a mod-3
|
||||
* behaviour:
|
||||
*
|
||||
*
|
||||
* * inside a quoted segment, a quote ends the segment.
|
||||
* * _immediately_ after ending a quoted segment, a quote
|
||||
* simply produces a literal quote.
|
||||
* * otherwise, outside a quoted segment, a quote begins a
|
||||
* quoted segment.
|
||||
*
|
||||
*
|
||||
* So, for example, if we started inside a quoted segment
|
||||
* then two contiguous quotes would close the segment and
|
||||
* produce a literal quote; three would close the segment,
|
||||
@ -303,10 +303,10 @@ void split_into_argv(char *cmdline, int *argc, char ***argv,
|
||||
*/
|
||||
while (*cmdline && isspace(*cmdline)) cmdline++;
|
||||
if (!*cmdline) {
|
||||
if (argc) *argc = 0;
|
||||
if (argv) *argv = NULL;
|
||||
if (argstart) *argstart = NULL;
|
||||
return;
|
||||
if (argc) *argc = 0;
|
||||
if (argv) *argv = NULL;
|
||||
if (argstart) *argstart = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -320,66 +320,66 @@ void split_into_argv(char *cmdline, int *argc, char ***argv,
|
||||
p = cmdline; q = outputline; outputargc = 0;
|
||||
|
||||
while (*p) {
|
||||
bool quote;
|
||||
bool quote;
|
||||
|
||||
/* Skip whitespace searching for start of argument. */
|
||||
while (*p && isspace(*p)) p++;
|
||||
if (!*p) break;
|
||||
/* Skip whitespace searching for start of argument. */
|
||||
while (*p && isspace(*p)) p++;
|
||||
if (!*p) break;
|
||||
|
||||
/* We have an argument; start it. */
|
||||
outputargv[outputargc] = q;
|
||||
outputargstart[outputargc] = p;
|
||||
outputargc++;
|
||||
quote = false;
|
||||
/* We have an argument; start it. */
|
||||
outputargv[outputargc] = q;
|
||||
outputargstart[outputargc] = p;
|
||||
outputargc++;
|
||||
quote = false;
|
||||
|
||||
/* Copy data into the argument until it's finished. */
|
||||
while (*p) {
|
||||
if (!quote && isspace(*p))
|
||||
break; /* argument is finished */
|
||||
/* Copy data into the argument until it's finished. */
|
||||
while (*p) {
|
||||
if (!quote && isspace(*p))
|
||||
break; /* argument is finished */
|
||||
|
||||
if (*p == '"' || *p == '\\') {
|
||||
/*
|
||||
* We have a sequence of zero or more backslashes
|
||||
* followed by a sequence of zero or more quotes.
|
||||
* Count up how many of each, and then deal with
|
||||
* them as appropriate.
|
||||
*/
|
||||
int i, slashes = 0, quotes = 0;
|
||||
while (*p == '\\') slashes++, p++;
|
||||
while (*p == '"') quotes++, p++;
|
||||
if (*p == '"' || *p == '\\') {
|
||||
/*
|
||||
* We have a sequence of zero or more backslashes
|
||||
* followed by a sequence of zero or more quotes.
|
||||
* Count up how many of each, and then deal with
|
||||
* them as appropriate.
|
||||
*/
|
||||
int i, slashes = 0, quotes = 0;
|
||||
while (*p == '\\') slashes++, p++;
|
||||
while (*p == '"') quotes++, p++;
|
||||
|
||||
if (!quotes) {
|
||||
/*
|
||||
* Special case: if there are no quotes,
|
||||
* slashes are not special at all, so just copy
|
||||
* n slashes to the output string.
|
||||
*/
|
||||
while (slashes--) *q++ = '\\';
|
||||
} else {
|
||||
/* Slashes annihilate in pairs. */
|
||||
while (slashes >= 2) slashes -= 2, *q++ = '\\';
|
||||
if (!quotes) {
|
||||
/*
|
||||
* Special case: if there are no quotes,
|
||||
* slashes are not special at all, so just copy
|
||||
* n slashes to the output string.
|
||||
*/
|
||||
while (slashes--) *q++ = '\\';
|
||||
} else {
|
||||
/* Slashes annihilate in pairs. */
|
||||
while (slashes >= 2) slashes -= 2, *q++ = '\\';
|
||||
|
||||
/* One remaining slash takes out the first quote. */
|
||||
if (slashes) quotes--, *q++ = '"';
|
||||
/* One remaining slash takes out the first quote. */
|
||||
if (slashes) quotes--, *q++ = '"';
|
||||
|
||||
if (quotes > 0) {
|
||||
/* Outside a quote segment, a quote starts one. */
|
||||
if (!quote) quotes--;
|
||||
if (quotes > 0) {
|
||||
/* Outside a quote segment, a quote starts one. */
|
||||
if (!quote) quotes--;
|
||||
|
||||
/* Now we produce (n+1)/3 literal quotes... */
|
||||
for (i = 3; i <= quotes+1; i += 3) *q++ = '"';
|
||||
/* Now we produce (n+1)/3 literal quotes... */
|
||||
for (i = 3; i <= quotes+1; i += 3) *q++ = '"';
|
||||
|
||||
/* ... and end in a quote segment iff 3 divides n. */
|
||||
quote = (quotes % 3 == 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*q++ = *p++;
|
||||
}
|
||||
}
|
||||
/* ... and end in a quote segment iff 3 divides n. */
|
||||
quote = (quotes % 3 == 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*q++ = *p++;
|
||||
}
|
||||
}
|
||||
|
||||
/* At the end of an argument, just append a trailing NUL. */
|
||||
*q++ = '\0';
|
||||
/* At the end of an argument, just append a trailing NUL. */
|
||||
*q++ = '\0';
|
||||
}
|
||||
|
||||
outputargv = sresize(outputargv, outputargc, char *);
|
||||
@ -497,96 +497,96 @@ int main(int argc, char **argv)
|
||||
int i, j;
|
||||
|
||||
if (argc > 1) {
|
||||
/*
|
||||
* Generation of tests.
|
||||
*
|
||||
* Given `-splat <args>', we print out a C-style
|
||||
* representation of each argument (in the form "a", "b",
|
||||
* NULL), backslash-escaping each backslash and double
|
||||
* quote.
|
||||
*
|
||||
* Given `-split <string>', we first doctor `string' by
|
||||
* turning forward slashes into backslashes, single quotes
|
||||
* into double quotes and underscores into spaces; and then
|
||||
* we feed the resulting string to ourself with `-splat'.
|
||||
*
|
||||
* Given `-generate', we concoct a variety of fun test
|
||||
* cases, encode them in quote-safe form (mapping \, " and
|
||||
* space to /, ' and _ respectively) and feed each one to
|
||||
* `-split'.
|
||||
*/
|
||||
if (!strcmp(argv[1], "-splat")) {
|
||||
int i;
|
||||
char *p;
|
||||
for (i = 2; i < argc; i++) {
|
||||
putchar('"');
|
||||
for (p = argv[i]; *p; p++) {
|
||||
if (*p == '\\' || *p == '"')
|
||||
putchar('\\');
|
||||
putchar(*p);
|
||||
}
|
||||
printf("\", ");
|
||||
}
|
||||
printf("NULL");
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Generation of tests.
|
||||
*
|
||||
* Given `-splat <args>', we print out a C-style
|
||||
* representation of each argument (in the form "a", "b",
|
||||
* NULL), backslash-escaping each backslash and double
|
||||
* quote.
|
||||
*
|
||||
* Given `-split <string>', we first doctor `string' by
|
||||
* turning forward slashes into backslashes, single quotes
|
||||
* into double quotes and underscores into spaces; and then
|
||||
* we feed the resulting string to ourself with `-splat'.
|
||||
*
|
||||
* Given `-generate', we concoct a variety of fun test
|
||||
* cases, encode them in quote-safe form (mapping \, " and
|
||||
* space to /, ' and _ respectively) and feed each one to
|
||||
* `-split'.
|
||||
*/
|
||||
if (!strcmp(argv[1], "-splat")) {
|
||||
int i;
|
||||
char *p;
|
||||
for (i = 2; i < argc; i++) {
|
||||
putchar('"');
|
||||
for (p = argv[i]; *p; p++) {
|
||||
if (*p == '\\' || *p == '"')
|
||||
putchar('\\');
|
||||
putchar(*p);
|
||||
}
|
||||
printf("\", ");
|
||||
}
|
||||
printf("NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "-split") && argc > 2) {
|
||||
char *str = malloc(20 + strlen(argv[0]) + strlen(argv[2]));
|
||||
char *p, *q;
|
||||
if (!strcmp(argv[1], "-split") && argc > 2) {
|
||||
char *str = malloc(20 + strlen(argv[0]) + strlen(argv[2]));
|
||||
char *p, *q;
|
||||
|
||||
q = str + sprintf(str, "%s -splat ", argv[0]);
|
||||
printf(" {\"");
|
||||
for (p = argv[2]; *p; p++, q++) {
|
||||
switch (*p) {
|
||||
case '/': printf("\\\\"); *q = '\\'; break;
|
||||
case '\'': printf("\\\""); *q = '"'; break;
|
||||
case '_': printf(" "); *q = ' '; break;
|
||||
default: putchar(*p); *q = *p; break;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
printf("\", {");
|
||||
fflush(stdout);
|
||||
q = str + sprintf(str, "%s -splat ", argv[0]);
|
||||
printf(" {\"");
|
||||
for (p = argv[2]; *p; p++, q++) {
|
||||
switch (*p) {
|
||||
case '/': printf("\\\\"); *q = '\\'; break;
|
||||
case '\'': printf("\\\""); *q = '"'; break;
|
||||
case '_': printf(" "); *q = ' '; break;
|
||||
default: putchar(*p); *q = *p; break;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
printf("\", {");
|
||||
fflush(stdout);
|
||||
|
||||
system(str);
|
||||
system(str);
|
||||
|
||||
printf("}},\n");
|
||||
printf("}},\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "-generate")) {
|
||||
char *teststr, *p;
|
||||
int i, initialquote, backslashes, quotes;
|
||||
if (!strcmp(argv[1], "-generate")) {
|
||||
char *teststr, *p;
|
||||
int i, initialquote, backslashes, quotes;
|
||||
|
||||
teststr = malloc(200 + strlen(argv[0]));
|
||||
teststr = malloc(200 + strlen(argv[0]));
|
||||
|
||||
for (initialquote = 0; initialquote <= 1; initialquote++) {
|
||||
for (backslashes = 0; backslashes < 5; backslashes++) {
|
||||
for (quotes = 0; quotes < 9; quotes++) {
|
||||
p = teststr + sprintf(teststr, "%s -split ", argv[0]);
|
||||
if (initialquote) *p++ = '\'';
|
||||
*p++ = 'a';
|
||||
for (i = 0; i < backslashes; i++) *p++ = '/';
|
||||
for (i = 0; i < quotes; i++) *p++ = '\'';
|
||||
*p++ = 'b';
|
||||
*p++ = '_';
|
||||
*p++ = 'c';
|
||||
*p++ = '\'';
|
||||
*p++ = '_';
|
||||
*p++ = 'd';
|
||||
*p = '\0';
|
||||
for (initialquote = 0; initialquote <= 1; initialquote++) {
|
||||
for (backslashes = 0; backslashes < 5; backslashes++) {
|
||||
for (quotes = 0; quotes < 9; quotes++) {
|
||||
p = teststr + sprintf(teststr, "%s -split ", argv[0]);
|
||||
if (initialquote) *p++ = '\'';
|
||||
*p++ = 'a';
|
||||
for (i = 0; i < backslashes; i++) *p++ = '/';
|
||||
for (i = 0; i < quotes; i++) *p++ = '\'';
|
||||
*p++ = 'b';
|
||||
*p++ = '_';
|
||||
*p++ = 'c';
|
||||
*p++ = '\'';
|
||||
*p++ = '_';
|
||||
*p++ = 'd';
|
||||
*p = '\0';
|
||||
|
||||
system(teststr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
system(teststr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "unrecognised option: \"%s\"\n", argv[1]);
|
||||
return 1;
|
||||
fprintf(stderr, "unrecognised option: \"%s\"\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -595,31 +595,31 @@ int main(int argc, char **argv)
|
||||
*/
|
||||
|
||||
for (i = 0; i < lenof(argv_tests); i++) {
|
||||
int ac;
|
||||
char **av;
|
||||
int ac;
|
||||
char **av;
|
||||
|
||||
split_into_argv(argv_tests[i].cmdline, &ac, &av);
|
||||
split_into_argv(argv_tests[i].cmdline, &ac, &av);
|
||||
|
||||
for (j = 0; j < ac && argv_tests[i].argv[j]; j++) {
|
||||
if (strcmp(av[j], argv_tests[i].argv[j])) {
|
||||
printf("failed test %d (|%s|) arg %d: |%s| should be |%s|\n",
|
||||
i, argv_tests[i].cmdline,
|
||||
j, av[j], argv_tests[i].argv[j]);
|
||||
}
|
||||
for (j = 0; j < ac && argv_tests[i].argv[j]; j++) {
|
||||
if (strcmp(av[j], argv_tests[i].argv[j])) {
|
||||
printf("failed test %d (|%s|) arg %d: |%s| should be |%s|\n",
|
||||
i, argv_tests[i].cmdline,
|
||||
j, av[j], argv_tests[i].argv[j]);
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
else {
|
||||
printf("test %d (|%s|) arg %d: |%s| == |%s|\n",
|
||||
i, argv_tests[i].cmdline,
|
||||
j, av[j], argv_tests[i].argv[j]);
|
||||
}
|
||||
else {
|
||||
printf("test %d (|%s|) arg %d: |%s| == |%s|\n",
|
||||
i, argv_tests[i].cmdline,
|
||||
j, av[j], argv_tests[i].argv[j]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (j < ac)
|
||||
printf("failed test %d (|%s|): %d args returned, should be %d\n",
|
||||
i, argv_tests[i].cmdline, ac, j);
|
||||
if (argv_tests[i].argv[j])
|
||||
printf("failed test %d (|%s|): %d args returned, should be more\n",
|
||||
i, argv_tests[i].cmdline, ac);
|
||||
}
|
||||
if (j < ac)
|
||||
printf("failed test %d (|%s|): %d args returned, should be %d\n",
|
||||
i, argv_tests[i].cmdline, ac, j);
|
||||
if (argv_tests[i].argv[j])
|
||||
printf("failed test %d (|%s|): %d args returned, should be more\n",
|
||||
i, argv_tests[i].cmdline, ac);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -13,7 +13,7 @@ void platform_get_x11_auth(struct X11Display *disp, Conf *conf)
|
||||
{
|
||||
char *xauthpath = conf_get_filename(conf, CONF_xauthfile)->path;
|
||||
if (xauthpath[0])
|
||||
x11_get_auth_from_authfile(disp, xauthpath);
|
||||
x11_get_auth_from_authfile(disp, xauthpath);
|
||||
}
|
||||
|
||||
const bool platform_uses_x11_unix_by_default = false;
|
||||
|
Reference in New Issue
Block a user