2
* Copyright (c) 2005 Massachusetts Institute of Technology
4
* Copyright (2) 2007 Secure Endpoints Inc.
6
* Permission is hereby granted, free of charge, to any person
7
* obtaining a copy of this software and associated documentation
8
* files (the "Software"), to deal in the Software without
9
* restriction, including without limitation the rights to use, copy,
10
* modify, merge, publish, distribute, sublicense, and/or sell copies
11
* of the Software, and to permit persons to whom the Software is
12
* furnished to do so, subject to the following conditions:
14
* The above copyright notice and this permission notice shall be
15
* included in all copies or substantial portions of the Software.
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
#include<netidmgr_intver.h>
33
/* used for the command-line help dialog */
39
#if defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL)
40
/* needed for writing out leaked allocation and handle report */
46
HINSTANCE khm_hInstance;
47
const wchar_t * khm_facility = L"NetIDMgr";
49
khm_ui_4 khm_commctl_version = 0;
51
khm_startup_options khm_startup;
53
const khm_version app_version = {KH_VERSION_LIST};
55
HRESULT hr_coinitialize = S_OK;
57
#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))
59
KHMEXP void KHMAPI khcint_dump_handles(FILE * f);
60
KHMEXP void KHMAPI perf_dump(FILE * f);
61
KHMEXP void KHMAPI kmqint_dump(FILE * f);
65
void khm_init_gui(void) {
67
hr_coinitialize = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
76
khm_init_taskbar_funcs();
79
void khm_exit_gui(void) {
80
khm_exit_taskbar_funcs();
89
if (hr_coinitialize == S_OK ||
90
hr_coinitialize == S_FALSE) {
95
/* This is passed into EnumResourceLanguages(). This returns the
96
language ID of the first resource of the type and name that's
97
passed into it. For the resources types we care about, we only
98
expect there to be one resource for a given name. At the moment we
99
don't support resource modules that contain resources for multiple
102
khm_enum_res_lang_proc_first(HANDLE hModule,
108
WORD * plangid = (WORD *) lParam;
110
*plangid = wIDLanguage;
115
#define KHM_RTF_RESOURCE L"KHMRTFRESOURCE"
118
khm_cmdline_dlg_proc(HWND hwnd,
126
WORD langID = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
127
HRSRC h_resinfo = NULL;
128
HGLOBAL h_resource = NULL;
129
LPVOID h_resmem = NULL;
132
SetDlgItemText(hwnd, IDC_PRODUCT,
133
TEXT(KH_VERSTR_PRODUCT_1033));
134
#ifdef OVERRIDE_COPYRIGHT
135
SetDlgItemText(hwnd, IDC_COPYRIGHT,
136
TEXT(KH_VERSTR_COPYRIGHT_1033));
139
EnumResourceLanguages(khm_hInstance,
141
MAKEINTRESOURCE(IDR_CMDLINERTF),
142
khm_enum_res_lang_proc_first,
145
h_resinfo = FindResourceEx(khm_hInstance,
147
MAKEINTRESOURCE(IDR_CMDLINERTF),
149
if (h_resinfo == NULL)
152
h_resource = LoadResource(khm_hInstance, h_resinfo);
153
if (h_resinfo == NULL)
156
h_resmem = LockResource(h_resource);
157
if (h_resmem == NULL)
160
ste.flags = ST_DEFAULT;
161
ste.codepage = CP_ACP;
163
SendDlgItemMessage(hwnd, IDC_CONTENT, EM_SETTEXTEX, (WPARAM) &ste, (LPARAM) h_resmem);
165
/* none of the above handles need to be freed. */
173
if (wParam == MAKEWPARAM(IDOK, BN_CLICKED)) {
174
EndDialog(hwnd, KHM_ERROR_EXIT);
181
EndDialog(hwnd, KHM_ERROR_EXIT);
189
void khm_show_commandline_help(void) {
192
hm_richedit = LoadLibrary(L"riched20.dll");
193
if (hm_richedit == NULL)
196
DialogBox(khm_hInstance, MAKEINTRESOURCE(IDD_CMDLINE),
197
NULL, khm_cmdline_dlg_proc);
199
FreeLibrary(hm_richedit);
202
void khm_parse_commandline(void) {
208
ZeroMemory(&khm_startup, sizeof(khm_startup));
210
wcmdline = GetCommandLine();
211
wargs = CommandLineToArgvW(wcmdline, &wargc);
213
for (i=1; i<wargc; i++) {
214
if (!wcscmp(wargs[i], L"-i") ||
215
!wcscmp(wargs[i], L"--kinit") ||
216
!wcscmp(wargs[i], L"-kinit")) {
217
khm_startup.init = TRUE;
218
khm_startup.exit = TRUE;
219
khm_startup.no_main_window = TRUE;
220
khm_startup.display |= SOPTS_DISPLAY_NODEF;
222
else if (!wcscmp(wargs[i], L"-m") ||
223
!wcscmp(wargs[i], L"--import") ||
224
!wcscmp(wargs[i], L"-import")) {
225
khm_startup.import = TRUE;
226
khm_startup.exit = TRUE;
227
khm_startup.no_main_window = TRUE;
228
khm_startup.display |= SOPTS_DISPLAY_NODEF;
230
else if (!wcscmp(wargs[i], L"-r") ||
231
!wcscmp(wargs[i], L"--renew") ||
232
!wcscmp(wargs[i], L"-renew")) {
233
khm_startup.renew = TRUE;
234
khm_startup.exit = TRUE;
235
khm_startup.no_main_window = TRUE;
236
khm_startup.display |= SOPTS_DISPLAY_NODEF;
238
else if (!wcscmp(wargs[i], L"-d") ||
239
!wcscmp(wargs[i], L"--destroy") ||
240
!wcscmp(wargs[i], L"-destroy")) {
241
khm_startup.destroy = TRUE;
242
khm_startup.exit = TRUE;
243
khm_startup.no_main_window = TRUE;
244
khm_startup.display |= SOPTS_DISPLAY_NODEF;
246
else if (!wcscmp(wargs[i], L"-a") ||
247
!wcscmp(wargs[i], L"--autoinit") ||
248
!wcscmp(wargs[i], L"-autoinit")) {
249
khm_startup.autoinit = TRUE;
250
khm_startup.display |= SOPTS_DISPLAY_NODEF;
252
else if (!wcscmp(wargs[i], L"-x") ||
253
!wcscmp(wargs[i], L"--exit") ||
254
!wcscmp(wargs[i], L"-exit")) {
255
khm_startup.exit = TRUE;
256
khm_startup.remote_exit = TRUE;
257
khm_startup.no_main_window = TRUE;
258
khm_startup.display |= SOPTS_DISPLAY_NODEF;
260
else if (!wcscmp(wargs[i], L"--minimized")) {
261
khm_startup.no_main_window = TRUE;
262
khm_startup.display |= SOPTS_DISPLAY_NODEF;
264
else if (!wcscmp(wargs[i], L"--show")) {
265
if (khm_startup.display & SOPTS_DISPLAY_HIDE) {
266
khm_show_commandline_help();
267
khm_startup.error_exit = TRUE;
271
khm_startup.display |= (SOPTS_DISPLAY_SHOW | SOPTS_DISPLAY_NODEF);
273
else if (!wcscmp(wargs[i], L"--hide")) {
274
if (khm_startup.display & SOPTS_DISPLAY_SHOW) {
275
khm_show_commandline_help();
276
khm_startup.error_exit = TRUE;
280
khm_startup.display |= (SOPTS_DISPLAY_HIDE | SOPTS_DISPLAY_NODEF);
281
khm_startup.no_main_window = TRUE;
284
khm_show_commandline_help();
286
khm_startup.error_exit = TRUE;
291
/* special: always enable renew when other options aren't specified */
292
if (!khm_startup.exit &&
293
!khm_startup.destroy &&
295
!khm_startup.remote_exit &&
296
!khm_startup.display)
297
khm_startup.renew = TRUE;
300
void khm_register_window_classes(void) {
301
INITCOMMONCONTROLSEX ics;
303
ZeroMemory(&ics, sizeof(ics));
304
ics.dwSize = sizeof(ics);
310
ICC_LISTVIEW_CLASSES |
312
ICC_INTERNET_CLASSES |
313
#if (_WIN32_WINNT >= 0x501)
316
ICC_STANDARD_CLASSES :
321
InitCommonControlsEx(&ics);
323
khm_register_main_wnd_class();
324
khm_register_credwnd_class();
325
khm_register_htwnd_class();
326
khm_register_passwnd_class();
327
khm_register_newcredwnd_class();
328
khm_register_propertywnd_class();
331
void khm_unregister_window_classes(void) {
332
khm_unregister_main_wnd_class();
333
khm_unregister_credwnd_class();
334
khm_unregister_htwnd_class();
335
khm_unregister_passwnd_class();
336
khm_unregister_newcredwnd_class();
337
khm_unregister_propertywnd_class();
341
/* we support up to 16 simutaneous dialogs. In reality, more than two
342
is pretty unlikely. Property sheets are special and are handled
344
#define MAX_UI_DIALOGS 16
346
typedef struct tag_khui_dialog {
352
static khui_dialog khui_dialogs[MAX_UI_DIALOGS];
353
static int n_khui_dialogs = 0;
354
static HWND khui_modal_dialog = NULL;
355
static BOOL khui_main_window_active;
357
/* should only be called from the UI thread */
358
void khm_add_dialog(HWND dlg) {
359
if(n_khui_dialogs < MAX_UI_DIALOGS - 1) {
360
khui_dialogs[n_khui_dialogs].hwnd = dlg;
361
khui_dialogs[n_khui_dialogs].hwnd_next = NULL;
362
khui_dialogs[n_khui_dialogs].active = TRUE;
371
/* should only be called from the UI thread */
372
void khm_enter_modal(HWND hwnd) {
375
if (khui_modal_dialog) {
377
/* we are already in a modal loop. */
380
assert(hwnd != khui_modal_dialog);
383
for (i=0; i < n_khui_dialogs; i++) {
384
if (khui_dialogs[i].hwnd == khui_modal_dialog) {
385
khui_dialogs[i].active = TRUE;
386
EnableWindow(khui_modal_dialog, FALSE);
392
assert(i < n_khui_dialogs);
395
for (i=0; i < n_khui_dialogs; i++) {
396
if (khui_dialogs[i].hwnd == hwnd) {
397
khui_dialogs[i].hwnd_next = khui_modal_dialog;
403
assert(i < n_khui_dialogs);
406
khui_modal_dialog = hwnd;
410
/* we are entering a modal loop. preserve the active state of
411
the overlapped dialogs and proceed with the modal
414
for (i=0; i < n_khui_dialogs; i++) {
415
if(khui_dialogs[i].hwnd != hwnd) {
416
khui_dialogs[i].active = IsWindowEnabled(khui_dialogs[i].hwnd);
417
EnableWindow(khui_dialogs[i].hwnd, FALSE);
421
khui_main_window_active = khm_is_main_window_active();
422
EnableWindow(khm_hwnd_main, FALSE);
424
khui_modal_dialog = hwnd;
426
SetForegroundWindow(hwnd);
430
/* should only be called from the UI thread */
431
void khm_leave_modal(void) {
434
for (i=0; i < n_khui_dialogs; i++) {
435
if (khui_dialogs[i].hwnd == khui_modal_dialog)
440
assert(i < n_khui_dialogs);
443
if (i < n_khui_dialogs && khui_dialogs[i].hwnd_next) {
445
/* we need to proceed to the next one down the modal dialog
446
chain. We are not exiting a modal loop. */
448
khui_modal_dialog = khui_dialogs[i].hwnd_next;
449
khui_dialogs[i].hwnd_next = FALSE;
451
EnableWindow(khui_modal_dialog, TRUE);
455
HWND last_dialog = NULL;
457
/* we are exiting a modal loop. */
459
for (i=0; i < n_khui_dialogs; i++) {
460
if(khui_dialogs[i].hwnd != khui_modal_dialog) {
461
EnableWindow(khui_dialogs[i].hwnd, khui_dialogs[i].active);
462
last_dialog = khui_dialogs[i].hwnd;
466
EnableWindow(khm_hwnd_main, TRUE);
468
khui_modal_dialog = NULL;
471
SetActiveWindow(last_dialog);
473
SetActiveWindow(khm_hwnd_main);
477
/* should only be called from the UI thread */
478
void khm_del_dialog(HWND dlg) {
480
for(i=0;i < n_khui_dialogs; i++) {
481
if(khui_dialogs[i].hwnd == dlg)
485
if(i < n_khui_dialogs)
490
for(;i < n_khui_dialogs; i++) {
491
khui_dialogs[i] = khui_dialogs[i+1];
495
BOOL khm_check_dlg_message(LPMSG pmsg) {
498
for(i=0;i<n_khui_dialogs;i++) {
499
if(IsDialogMessage(khui_dialogs[i].hwnd, pmsg)) {
508
BOOL khm_is_dialog_active(void) {
512
hwnd = GetForegroundWindow();
514
for (i=0; i<n_khui_dialogs; i++) {
515
if (khui_dialogs[i].hwnd == hwnd)
522
/* We support at most 256 property sheets simultaneously. 256
523
property sheets should be enough for everybody. */
524
#define MAX_UI_PROPSHEETS 256
526
khui_property_sheet *_ui_propsheets[MAX_UI_PROPSHEETS];
527
int _n_ui_propsheets = 0;
529
void khm_add_property_sheet(khui_property_sheet * s) {
530
if(_n_ui_propsheets < MAX_UI_PROPSHEETS)
531
_ui_propsheets[_n_ui_propsheets++] = s;
539
void khm_del_property_sheet(khui_property_sheet * s) {
542
for(i=0;i < _n_ui_propsheets; i++) {
543
if(_ui_propsheets[i] == s)
547
if(i < _n_ui_propsheets)
552
for(;i < _n_ui_propsheets; i++) {
553
_ui_propsheets[i] = _ui_propsheets[i+1];
557
BOOL khm_check_ps_message(LPMSG pmsg) {
559
khui_property_sheet * ps;
560
for(i=0;i<_n_ui_propsheets;i++) {
561
if(khui_ps_check_message(_ui_propsheets[i], pmsg)) {
562
if(_ui_propsheets[i]->status == KHUI_PS_STATUS_DONE) {
563
ps = _ui_propsheets[i];
565
ps->status = KHUI_PS_STATUS_DESTROY;
566
kmq_post_message(KMSG_CRED, KMSG_CRED_PP_END, 0, (void *) ps);
577
static HACCEL ha_menu;
579
WPARAM khm_message_loop_int(khm_boolean * p_exit) {
583
while((r = GetMessage(&msg, NULL, 0,0)) &&
584
(p_exit == NULL || *p_exit)) {
587
if(!khm_check_dlg_message(&msg) &&
588
!khm_check_ps_message(&msg) &&
589
!TranslateAccelerator(khm_hwnd_main, ha_menu, &msg)) {
590
TranslateMessage(&msg);
591
DispatchMessage(&msg);
598
WPARAM khm_message_loop(void) {
600
ha_menu = khui_create_global_accel_table();
601
w = khm_message_loop_int(NULL);
602
DestroyAcceleratorTable(ha_menu);
606
/* Handles all context closures which have a signalled error state.
607
If the context is a top level context, then the errors are
610
khm_err_ctx_completion_handler(enum kherr_ctx_event evt,
615
/* we only handle top level contexts here. For others, we allow
616
the child contexts to fold upward silently. */
617
if (c->parent || !kherr_is_error_i(c))
620
for(e = kherr_get_first_event(c);
622
e = kherr_get_next_event(e)) {
624
if (e->severity != KHERR_ERROR && e->severity != KHERR_WARNING)
627
kherr_evaluate_event(e);
629
/* we only report errors if there is enough information to
630
present a message. */
631
if (e->short_desc && e->long_desc) {
633
khui_alert_create_empty(&a);
635
khui_alert_set_severity(a, e->severity);
636
khui_alert_set_title(a, e->short_desc);
637
khui_alert_set_message(a, e->long_desc);
639
khui_alert_set_suggestion(a, e->suggestion);
643
khui_alert_release(a);
648
static wchar_t helpfile[MAX_PATH] = L"";
650
HWND khm_html_help(HWND hwnd, wchar_t * suffix,
651
UINT command, DWORD_PTR data) {
653
wchar_t gpath[MAX_PATH + MAX_PATH];
657
wchar_t ppath[MAX_PATH];
659
dw = GetModuleFileName(NULL, ppath, ARRAYLENGTH(ppath));
662
StringCbCopy(helpfile, sizeof(helpfile), NIDM_HELPFILE);
664
PathRemoveFileSpec(ppath);
665
PathAppend(ppath, NIDM_HELPFILE);
666
StringCbCopy(helpfile, sizeof(helpfile), ppath);
670
StringCbCopy(gpath, sizeof(gpath), helpfile);
673
StringCbCat(gpath, sizeof(gpath), suffix);
675
return HtmlHelp(hwnd, gpath, command, data);
678
void khm_load_default_modules(void) {
679
kmm_load_default_modules();
682
int khm_compare_version(const khm_version * v1, const khm_version * v2) {
684
if (v1->major != v2->major)
685
return ((int)v1->major) - ((int)v2->major);
687
if (v1->minor != v2->minor)
688
return ((int)v1->minor) - ((int)v2->minor);
690
if (v1->patch != v2->patch)
691
return ((int)v1->patch) - ((int)v2->patch);
693
return ((int)v1->aux - ((int)v2->aux));
696
int WINAPI WinMain(HINSTANCE hInstance,
697
HINSTANCE hPrevInstance,
704
int mutex_retries = 5;
706
khm_hInstance = hInstance;
707
khm_nCmdShow = nCmdShow;
709
khm_parse_commandline();
711
if (khm_startup.error_exit)
716
if (--mutex_retries < 0)
719
h_appmutex = CreateMutex(NULL, FALSE, L"Local\\NetIDMgr_GlobalAppMutex");
720
if (h_appmutex == NULL)
722
if (GetLastError() == ERROR_ALREADY_EXISTS)
725
khc_load_schema(NULL, schema_uiconfig);
731
PDESCTHREAD(L"UI", L"App");
733
/* set this so that we don't accidently invoke an API that
734
inadvertently puts up the new creds dialog at an
735
inopportune moment, like, say, during the new creds dialog
736
is open. This only affects this process, and any child
737
processes started by plugins. */
738
SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1");
742
khm_commctl_version = khm_get_commctl_version(NULL);
744
/* we only open a main window if this is the only instance
745
of the application that is running. */
750
kmq_set_completion_handler(KMSG_CRED, kmsg_cred_completion);
752
kherr_add_ctx_handler(khm_err_ctx_completion_handler,
756
/* load the standard plugins */
757
khm_load_default_modules();
759
khm_register_window_classes();
761
khm_init_request_daemon();
763
khm_create_main_window();
765
if (!khm_startup.no_main_window &&
766
nCmdShow != SW_SHOWMINNOACTIVE &&
767
nCmdShow != SW_MINIMIZE &&
768
nCmdShow != SW_SHOWMINIMIZED) {
770
khm_show_main_window();
773
khm_refresh_config();
775
rv = (int) khm_message_loop();
777
kmq_set_completion_handler(KMSG_CRED, NULL);
779
khm_exit_request_daemon();
783
khm_unregister_window_classes();
786
CloseHandle(h_appmutex);
789
/* There is an instance of NetIDMgr already running. */
794
wchar_t mapname[256];
797
khm_query_app_version query_app_version;
799
BOOL use_cmd_v1 = FALSE;
802
CloseHandle(h_appmutex);
804
while (hwnd == NULL && retries) {
805
hwnd = FindWindowEx(NULL, NULL, KHUI_MAIN_WINDOW_CLASS, NULL);
812
/* if the app was just starting, we might have to wait
813
till the main window is created. */
820
/* if the app was just exiting, we might see the mutex but
821
not the window. We go back and check if the mutex is
827
/* first check if the remote instance supports a version
830
StringCbPrintf(mapname, sizeof(mapname),
831
QUERY_APP_VER_MAP_FMT,
832
(tid = GetCurrentThreadId()));
834
hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
844
xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
845
sizeof(query_app_version));
847
ZeroMemory(&query_app_version, sizeof(query_app_version));
850
query_app_version.magic = KHM_QUERY_APP_VER_MAGIC;
851
query_app_version.code = KHM_ERROR_NOT_IMPLEMENTED;
852
query_app_version.ver_caller = app_version;
854
query_app_version.request_swap = TRUE;
856
memcpy(xfer, &query_app_version, sizeof(query_app_version));
858
SendMessage(hwnd, WM_KHUI_QUERY_APP_VERSION,
861
memcpy(&query_app_version, xfer, sizeof(query_app_version));
863
UnmapViewOfFile(xfer);
870
if (query_app_version.magic != KHM_QUERY_APP_VER_MAGIC ||
871
query_app_version.code != KHM_ERROR_SUCCESS) {
873
/* We managed to communicate with the remote instance, but
874
it didn't send us useful information. The remote
875
instance is not running an actual NetIDMgr instance.
876
However, it owns a top level window that was registered
877
with our classname. This instance won't function
878
properly if we let it proceed.
881
wchar_t error_msg[1024];
882
wchar_t error_title[256];
884
LoadString(khm_hInstance, IDS_REMOTE_FAIL_TITLE,
885
error_title, ARRAYLENGTH(error_title));
886
LoadString(khm_hInstance, IDS_REMOTE_FAIL,
887
error_msg, ARRAYLENGTH(error_msg));
889
MessageBox(NULL, error_msg, error_title,
892
goto done_with_remote;
895
if (query_app_version.code == KHM_ERROR_SUCCESS &&
896
query_app_version.request_swap) {
897
/* the request for swap was granted. We can now
898
initialize our instance as the master instance. */
904
/* Now we can work on sending the command-line to the remote
905
instance. However we need to figure out which version of
906
the startup structure it supports. */
912
if (khm_compare_version(&query_app_version.ver_remote, &app_version) == 0 ||
913
khm_compare_version(&query_app_version.ver_remote, &v) > 0)
918
StringCbPrintf(mapname, sizeof(mapname),
920
(tid = GetCurrentThreadId()));
922
cb = max(sizeof(khm_startup_options_v1),
923
sizeof(khm_startup_options_v2));
925
cb = UBOUNDSS(cb, 4096, 4096);
931
hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
944
/* use the v2 structure */
945
khm_startup_options_v3 opt;
946
khm_startup_options_v3 *xferopt;
948
ZeroMemory(&opt, sizeof(opt));
950
opt.v2opt.magic = STARTUP_OPTIONS_MAGIC;
952
opt.v2opt.init = khm_startup.init;
953
opt.v2opt.import = khm_startup.import;
954
opt.v2opt.renew = khm_startup.renew;
955
opt.v2opt.destroy = khm_startup.destroy;
956
opt.v2opt.autoinit = khm_startup.autoinit;
957
opt.v2opt.remote_exit = khm_startup.remote_exit;
958
opt.remote_display = khm_startup.display;
960
opt.v2opt.code = KHM_ERROR_NOT_IMPLEMENTED;
962
/* check if we can use the v3 options structure. This
963
should be possible for 1.3.1 and above. */
964
v.major = 1; v.minor = 3; v.patch = 1; v.aux = 0;
965
if (khm_compare_version(&query_app_version.ver_remote, &app_version) == 0 ||
966
khm_compare_version(&query_app_version.ver_remote, &v) >= 0) {
968
opt.v2opt.cb_size = sizeof(opt);
972
opt.v2opt.cb_size = sizeof(opt.v2opt);
976
xfer = MapViewOfFile(hmap,
981
xferopt = (khm_startup_options_v3 *) xfer;
984
memcpy(xfer, &opt, opt.v2opt.cb_size);
986
SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V2,
989
/* If it looks like the request was not processed, and
990
we were using a v3 request, fail-over to a v2
992
if (xferopt->v2opt.code == KHM_ERROR_NOT_IMPLEMENTED &&
993
opt.v2opt.cb_size == sizeof(opt)) {
995
opt.v2opt.cb_size = sizeof(opt.v2opt);
996
memcpy(xfer, &opt, opt.v2opt.cb_size);
998
SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V2,
1002
/* if it still looks like the request was not
1003
processed, we failover to a v1 call */
1004
if (xferopt->v2opt.code == KHM_ERROR_NOT_IMPLEMENTED) {
1007
memcpy(&opt, xfer, opt.v2opt.cb_size);
1010
UnmapViewOfFile(xfer);
1016
/* use the v1 structure */
1018
khm_startup_options_v1 v1opt;
1020
ZeroMemory(&v1opt, sizeof(v1opt));
1022
v1opt.init = khm_startup.init;
1023
v1opt.import = khm_startup.import;
1024
v1opt.renew = khm_startup.renew;
1025
v1opt.destroy = khm_startup.destroy;
1026
v1opt.autoinit = khm_startup.autoinit;
1028
xfer = MapViewOfFile(hmap,
1034
memcpy(xfer, &v1opt, sizeof(v1opt));
1036
SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V1,
1039
UnmapViewOfFile(xfer);
1050
#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))
1054
#if _MSC_VER >= 1400 && __STDC_WANT_SECURE_LIB__
1055
if (fopen_s(&f, "memleak.txt", "w") != 0)
1056
goto done_with_dump;
1058
f = fopen("memleak.txt", "w");
1060
goto done_with_dump;
1064
khcint_dump_handles(f);