/*********************************************************************** $Id: remap.c 1187 2008-09-10 21:58:04Z jbs $ Copyright (c) 1993, 1998 M. Kimes Copyright (c) 2004, 2008 Steven H.Levine 01 Aug 04 SHL Rework lstrip/rstrip usage 06 Aug 05 SHL Renames 22 Jul 06 SHL Check more run time errors 29 Jul 06 SHL Use xfgets 31 Aug 06 SHL Use _fsopen to avoid noise complaints 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat 29 Feb 08 GKY Use xfree where appropriate 19 Jul 08 GKY Replace save_dir2(dir) with pFM2SaveDirectory and use BldFullPathName 24 Aug 08 GKY Warn full drive on save of .DAT file; prevent loss of existing file ***********************************************************************/ #include #include #include #include // unlink #define INCL_DOS #define INCL_WIN #define INCL_LONGLONG // dircnrs.h #include "fm3dll.h" #include "fm3dlg.h" #include "fm3str.h" #include "errutil.h" // Dos_Error... #include "strutil.h" // GetPString #include "pathutil.h" // BldFullPathName #include "valid.h" // CheckDrive, FillInDriveFlags #include "remap.h" #include "wrappers.h" // xfgets #include "strips.h" // bstrip #include "misc.h" // CheckDriveSpaceAvail #include "systemf.h" // runemf2 #include "dirs.h" // save_dir2 #include "fortify.h" #pragma data_seg(DATA1) static PSZ pszSrcFile = __FILE__; typedef struct APPNOTIFY { HAPP happ; BOOL attach; BOOL failedonce; CHAR uncname[CCHMAXPATH]; CHAR device; struct APPNOTIFY *next; struct APPNOTIFY *prev; } APPNOTIFY; typedef struct LINKRES { CHAR *res; struct LINKRES *next; } LINKRES; static LINKRES *reshead = NULL; static BOOL loadedres = FALSE; #define MAXNUMRES 200 VOID load_resources(VOID) { /* load linked list of resources from RESOURCE.DAT file */ FILE *fp; LINKRES *info, *last = NULL; CHAR s[CCHMAXPATH + 14]; INT x = 0; loadedres = TRUE; BldFullPathName(s, pFM2SaveDirectory, "RESOURCE.DAT"); fp = _fsopen(s, "r", SH_DENYWR); if (fp) { while (x < MAXNUMRES && !feof(fp)) { if (!xfgets_bstripcr(s, sizeof(s), fp, pszSrcFile, __LINE__)) break; if (*s && *s != ';') { info = xmalloc(sizeof(LINKRES), pszSrcFile, __LINE__); if (info) { info->res = xstrdup(s, pszSrcFile, __LINE__); if (!info->res) free(info); else { x++; info->next = NULL; if (!reshead) reshead = info; else last->next = info; last = info; } } } } fclose(fp); } } VOID save_resources(VOID) { /* save linked list of resources to RESOURCE.DAT file */ LINKRES *info; FILE *fp; CHAR s[CCHMAXPATH + 14]; if (!loadedres) return; BldFullPathName(s, pFM2SaveDirectory, "RESOURCE.DAT"); if (CheckDriveSpaceAvail(s, ullDATFileSpaceNeeded, 1) == 2) return; //already gave error msg if (reshead) { fp = xfopen(s, "w", pszSrcFile, __LINE__); if (fp) { fputs(GetPString(IDS_REMOTEFILETEXT), fp); info = reshead; while (info) { fprintf(fp, "%0.*s\n", CCHMAXPATH, info->res); info = info->next; } fclose(fp); } } else unlink(s); } BOOL add_resource(CHAR * res) { LINKRES *info, *last = NULL; INT x = 0; if (!res || !*res) return FALSE; if (!loadedres) load_resources(); info = reshead; while (info) { if (!stricmp(info->res, res)) return FALSE; last = info; info = info->next; x++; } info = xmalloc(sizeof(LINKRES), pszSrcFile, __LINE__); if (info) { info->res = xstrdup(res, pszSrcFile, __LINE__); if (!info->res) free(info); else { info->next = NULL; if (!reshead) reshead = info; else last->next = info; if (x > MAXNUMRES) { info = reshead; reshead = reshead->next; free(info); } return TRUE; } } return FALSE; } BOOL remove_resource(CHAR * res) { LINKRES *info, *last = NULL; if (!res || !*res) return FALSE; if (!loadedres) load_resources(); info = reshead; while (info) { if (!stricmp(info->res, res)) { if (last) last->next = info->next; else reshead = info->next; xfree(info->res, pszSrcFile, __LINE__); free(info); return TRUE; } last = info; info = info->next; } return FALSE; } VOID free_resources(VOID) { LINKRES *info, *next; info = reshead; while (info) { next = info->next; xfree(info->res, pszSrcFile, __LINE__); free(info); info = next; } reshead = NULL; DosPostEventSem(CompactSem); } MRESULT EXPENTRY RemapDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { static BOOL fRemapped; static APPNOTIFY *apphead = NULL, *apptail = NULL; switch (msg) { case WM_INITDLG: WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, EM_SETTEXTLIMIT, MPFROM2SHORT(CCHMAXPATH, 0), MPVOID); fRemapped = FALSE; if (!loadedres) load_resources(); { LINKRES *info; info = reshead; while (info) { WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, LM_INSERTITEM, MPFROM2SHORT(LIT_END, 0), MPFROMP(info->res)); info = info->next; } } { ULONG ulDriveMap, ulDriveNum, x, ulType; CHAR s[3] = " :"; DosError(FERR_DISABLEHARDERR); if (!DosQCurDisk(&ulDriveNum, &ulDriveMap)) { for (x = 0; x < 26; x++) { if (!(driveflags[x] & DRIVE_IGNORE)) { *s = (CHAR) x + 'A'; if (!(ulDriveMap & (1 << x))) WinSendDlgItemMsg(hwnd, MAP_ATTACHLIST, LM_INSERTITEM, MPFROM2SHORT(LIT_END, 0), MPFROMP(s)); else { CheckDrive((CHAR) x + 'A', NULL, &ulType); if (ulType & DRIVE_REMOTE) WinSendDlgItemMsg(hwnd, MAP_DETACHLIST, LM_INSERTITEM, MPFROM2SHORT(LIT_END, 0), MPFROMP(s)); } } } } else WinDismissDlg(hwnd, 0); } break; case WM_CONTROL: switch (SHORT1FROMMP(mp1)) { case MAP_ATTACHLIST: switch (SHORT2FROMMP(mp1)) { case LN_ENTER: PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(MAP_ATTACH, 0), MPVOID); break; } break; case MAP_DETACHLIST: switch (SHORT2FROMMP(mp1)) { case LN_ENTER: PostMsg(hwnd, WM_COMMAND, MPFROM2SHORT(MAP_DETACH, 0), MPVOID); break; case LN_SELECT: { SHORT x; CHAR d[3]; WinSetDlgItemText(hwnd, MAP_ATTACHTO, NullStr); x = (SHORT) WinSendDlgItemMsg(hwnd, MAP_DETACHLIST, LM_QUERYSELECTION, MPFROMSHORT(LIT_FIRST), MPVOID); if (x >= 0) { *d = 0; WinSendDlgItemMsg(hwnd, MAP_DETACHLIST, LM_QUERYITEMTEXT, MPFROM2SHORT(x, sizeof(d)), MPFROMP(d)); if (*d) { CHAR buf[2048]; ULONG len; APIRET rc; FSQBUFFER2 *p2; memset(buf, 0, sizeof(buf)); len = sizeof(buf); p2 = (FSQBUFFER2 *) buf; DosError(FERR_DISABLEHARDERR); rc = DosQueryFSAttach(d, 0, FSAIL_QUERYNAME, p2, &len); if (!rc) { CHAR *p; p = (char *)p2->szName; p += p2->cbName + 1; p += p2->cbFSDName + 1; if (p2->cbFSAData) WinSetDlgItemText(hwnd, MAP_ATTACHTO, p); else WinSetDlgItemText(hwnd, MAP_ATTACHTO, GetPString(IDS_UNKNOWNBRKTTEXT)); } else WinSetDlgItemText(hwnd, MAP_ATTACHTO, GetPString(IDS_UNKNOWNBRKTTEXT)); } } } break; } break; } break; case WM_APPTERMINATENOTIFY: { APPNOTIFY *info; SHORT x, c; CHAR d[3]; HWND hwndList; if (!mp2) fRemapped = TRUE; info = apphead; GetRidOfIt: while (info) { if (info->happ == (HAPP) mp1) { /* Note: if this next line is removed, FM/2 will start the attach/detach * request again, once for each request, to see if it might succeed and to * ensure the request is seen by the user in case interaction is required. */ info->failedonce = TRUE; hwndList = WinWindowFromID(hwnd, (info->attach) ? MAP_ATTACHLIST : MAP_DETACHLIST); if (!mp2 || (ULONG) mp2 == 1041 || info->failedonce) { if (info->prev) info->prev->next = info->next; if (info->next) info->next->prev = info->prev; if (apphead == info) apphead = info->next; if (apptail == info) apptail = info->prev; } if (!mp2) { if (*info->uncname && stricmp(info->uncname, GetPString(IDS_UNKNOWNBRKTTEXT)) && add_resource(info->uncname)) { save_resources(); WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, LM_INSERTITEM, MPFROM2SHORT(LIT_END, 0), MPFROMP(info->uncname)); } c = (SHORT) WinSendMsg(hwndList, LM_QUERYITEMCOUNT, MPVOID, MPVOID); if (c > 0) { for (x = 0; x < c; x++) { *d = 0; WinSendMsg(hwndList, LM_QUERYITEMTEXT, MPFROM2SHORT(x, sizeof(d)), MPFROMP(d)); if (*d == info->device) { WinSendMsg(hwndList, LM_DELETEITEM, MPFROMSHORT(x), MPVOID); hwndList = WinWindowFromID(hwnd, (info->attach) ? MAP_DETACHLIST : MAP_ATTACHLIST); d[1] = ':'; d[2] = 0; WinSendMsg(hwndList, LM_INSERTITEM, MPFROM2SHORT(LIT_SORTASCENDING, 0), MPFROMP(d)); break; } } } } else if ((ULONG) mp2 != 1041 && !info->failedonce) { PROGDETAILS pgd; CHAR params[368], *p; HAPP happ; *d = info->device; d[1] = ':'; d[2] = 0; p = GetCmdSpec(FALSE); memset(&pgd, 0, sizeof(pgd)); pgd.Length = sizeof(pgd); pgd.progt.progc = PROG_WINDOWABLEVIO; pgd.progt.fbVisible = SHE_VISIBLE; pgd.pszTitle = (info->attach) ? GetPString(IDS_ATTACHREQTEXT) : GetPString(IDS_DETACHREQTEXT); pgd.pszExecutable = p; pgd.pszParameters = params; pgd.pszStartupDir = NULL; pgd.pszIcon = NULL; pgd.pszEnvironment = NULL; pgd.swpInitial.hwndInsertBehind = HWND_TOP; pgd.swpInitial.hwnd = hwnd; pgd.swpInitial.fl = SWP_SHOW | SWP_ACTIVATE; if (info->attach) sprintf(params, "/C NET USE %s \"%s\"", d, info->uncname); else sprintf(params, "/C NET USE %s /D", d); info->failedonce = TRUE; happ = WinStartApp(hwnd, &pgd, pgd.pszParameters, NULL, SAF_MAXIMIZED); if (!happ) goto GetRidOfIt; info->happ = happ; break; } else if ((ULONG) mp2 == 1041) saymsg(MB_CANCEL | MB_ICONEXCLAMATION, hwnd, GetPString(IDS_ERRORTEXT), "%s", GetPString(IDS_CANTSTARTNETUSETEXT)); if (!mp2 || (ULONG) mp2 == 1041 || info->failedonce) free(info); break; } info = info->next; } } break; case WM_COMMAND: switch (SHORT1FROMMP(mp1)) { case MAP_DELETE: { SHORT x; CHAR resource[CCHMAXPATH]; x = (SHORT) WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, LM_QUERYSELECTION, MPFROMSHORT(LIT_FIRST), MPVOID); if (x >= 0) { *resource = 0; WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, LM_QUERYITEMTEXT, MPFROM2SHORT(x, sizeof(resource)), MPFROMP(resource)); bstrip(resource); if (*resource) { if (remove_resource(resource)) { save_resources(); WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, LM_DELETEITEM, MPFROMSHORT(x), MPVOID); if (x) x--; WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, LM_SELECTITEM, MPFROMSHORT(x), MPFROMSHORT(TRUE)); if (!(SHORT) WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, LM_QUERYITEMCOUNT, MPVOID, MPVOID)) WinSetDlgItemText(hwnd, MAP_ATTACHTO, NullStr); } } } } break; case MAP_CLEAR: free_resources(); save_resources(); WinSendDlgItemMsg(hwnd, MAP_ATTACHTO, LM_DELETEALL, MPVOID, MPVOID); WinSetDlgItemText(hwnd, MAP_ATTACHTO, NullStr); break; case MAP_INFO: case MAP_DETACH: { CHAR d[3], s[CCHMAXPATH]; SHORT x; *s = 0; WinQueryDlgItemText(hwnd, MAP_ATTACHTO, sizeof(s), s); bstrip(s); x = (SHORT) WinSendDlgItemMsg(hwnd, MAP_DETACHLIST, LM_QUERYSELECTION, MPFROMSHORT(LIT_FIRST), MPVOID); if (x >= 0) { *d = 0; WinSendDlgItemMsg(hwnd, MAP_DETACHLIST, LM_QUERYITEMTEXT, MPFROM2SHORT(x, sizeof(d)), MPFROMP(d)); if (*d) { switch (SHORT1FROMMP(mp1)) { case MAP_DETACH: { PROGDETAILS pgd; CHAR params[368], *p; HAPP happ; p = GetCmdSpec(FALSE); memset(&pgd, 0, sizeof(pgd)); pgd.Length = sizeof(pgd); pgd.progt.progc = PROG_WINDOWABLEVIO; pgd.progt.fbVisible = SHE_VISIBLE; pgd.pszTitle = GetPString(IDS_DETACHREQTEXT); pgd.pszExecutable = p; pgd.pszParameters = params; pgd.pszStartupDir = NULL; pgd.pszIcon = NULL; pgd.pszEnvironment = NULL; pgd.swpInitial.hwndInsertBehind = HWND_TOP; pgd.swpInitial.hwnd = hwnd; pgd.swpInitial.fl = SWP_SHOW | SWP_ACTIVATE; sprintf(params, "/C NET USE %s /D", d); happ = WinStartApp(hwnd, &pgd, pgd.pszParameters, NULL, SAF_MAXIMIZED); if (happ) { APPNOTIFY *info; WinSetDlgItemText(hwnd, MAP_ATTACHTO, NullStr); info = xmallocz(sizeof(APPNOTIFY), pszSrcFile, __LINE__); if (info) { info->happ = happ; info->attach = FALSE; info->failedonce = FALSE; strcpy(info->uncname, s); info->device = *d; if (!apphead) apphead = info; else { apptail->next = info; info->prev = apptail; } apptail = info; } } else saymsg(MB_CANCEL | MB_ICONEXCLAMATION, hwnd, GetPString(IDS_ERRORTEXT), GetPString(IDS_CANTSTARTTEXT), p, params); } #ifdef NEVER // fixme to be gone? DosError(FERR_DISABLEHARDERR); rc = DosFSAttach(d, s, d, strlen(d) + 1, FS_DETACH); if (rc) { Dos_Error(MB_CANCEL, rc, hwnd, pszSrcFile, __LINE__, GetPString(IDS_DETACHFAILEDTEXT), d, s); } else { fRemapped = TRUE; WinSendDlgItemMsg(hwnd, MAP_DETACHLIST, LM_DELETEITEM, MPFROMSHORT(x), MPVOID); WinSendDlgItemMsg(hwnd, MAP_ATTACHLIST, LM_INSERTITEM, MPFROM2SHORT(LIT_SORTASCENDING, 0), MPFROMP(d)); } #endif // fixme to be gone? break; case MAP_INFO: runemf2(SEPARATEKEEP | WINDOWED | MAXIMIZED, hwnd, pszSrcFile, __LINE__, NULL, NULL, "%s /C NET USE %s", GetCmdSpec(FALSE), d); break; } } } } break; case MAP_ATTACH: { CHAR d[3], s[CCHMAXPATH]; SHORT x; *s = 0; WinQueryDlgItemText(hwnd, MAP_ATTACHTO, sizeof(s), s); bstrip(s); if (*s) { x = (SHORT) WinSendDlgItemMsg(hwnd, MAP_ATTACHLIST, LM_QUERYSELECTION, MPFROMSHORT(LIT_FIRST), MPVOID); if (x >= 0) { *d = 0; WinSendDlgItemMsg(hwnd, MAP_ATTACHLIST, LM_QUERYITEMTEXT, MPFROM2SHORT(x, sizeof(d)), MPFROMP(d)); if (*d) { PROGDETAILS pgd; CHAR params[368], *p; HAPP happ; p = GetCmdSpec(FALSE); memset(&pgd, 0, sizeof(pgd)); pgd.Length = sizeof(pgd); pgd.progt.progc = PROG_WINDOWABLEVIO; pgd.progt.fbVisible = SHE_VISIBLE; pgd.pszTitle = GetPString(IDS_ATTACHREQTEXT); pgd.pszExecutable = p; pgd.pszParameters = params; pgd.pszStartupDir = NULL; pgd.pszIcon = NULL; pgd.pszEnvironment = NULL; pgd.swpInitial.hwndInsertBehind = HWND_TOP; pgd.swpInitial.hwnd = hwnd; pgd.swpInitial.fl = SWP_SHOW | SWP_ACTIVATE; sprintf(params, "/C NET USE %s \"%s\"", d, s); happ = WinStartApp(hwnd, &pgd, pgd.pszParameters, NULL, SAF_MAXIMIZED); if (happ) { APPNOTIFY *info; info = xmallocz(sizeof(APPNOTIFY), pszSrcFile, __LINE__); if (info) { info->happ = happ; info->attach = TRUE; info->failedonce = FALSE; strcpy(info->uncname, s); info->device = *d; if (!apphead) apphead = info; else { apptail->next = info; info->prev = apptail; } apptail = info; } } else saymsg(MB_CANCEL | MB_ICONEXCLAMATION, hwnd, GetPString(IDS_ERRORTEXT), GetPString(IDS_CANTSTARTTEXT), p, params); #ifdef NEVER // fixme to be gone? DosError(FERR_DISABLEHARDERR); rc = DosFSAttach(d, s, s, strlen(s) + 1, FS_ATTACH); if (rc) { Dos_Error(MB_CANCEL, rc, hwnd, pszSrcFile, __LINE__, GetPString(IDS_ATTACHFAILEDTEXT), s, d); } else { fRemapped = TRUE; WinSendDlgItemMsg(hwnd, MAP_ATTACHLIST, LM_DELETEITEM, MPFROMSHORT(x), MPVOID); WinSendDlgItemMsg(hwnd, MAP_DETACHLIST, LM_INSERTITEM, MPFROM2SHORT(LIT_SORTASCENDING, 0), MPFROMP(d)); } #endif // fixme to be gone? } } } } break; case IDM_HELP: if (hwndHelp) WinSendMsg(hwndHelp, HM_DISPLAY_HELP, MPFROM2SHORT(HELP_REMAP, 0), MPFROMSHORT(HM_RESOURCEID)); break; case DID_CANCEL: if (fRemapped) { if (hwndTree) PostMsg(hwndTree, WM_COMMAND, MPFROM2SHORT(IDM_RESCAN, 0), MPVOID); else FillInDriveFlags(NULL); if (hwndMain) PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID); } WinDismissDlg(hwnd, 0); break; } return 0; case WM_DESTROY: if (apphead) { APPNOTIFY *info, *next; info = apphead; while (info) { next = info->next; free(info); info = next; } apphead = apptail = NULL; saymsg(MB_YESNOCANCEL, HWND_DESKTOP, GetPString(IDS_NOTICETITLETEXT), "%s", GetPString(IDS_REMAPNOTICETEXT)); } free_resources(); loadedres = FALSE; break; } return WinDefDlgProc(hwnd, msg, mp1, mp2); } #pragma alloc_text(FMREMAP,RemapDlgProc,load_resources,save_resources) #pragma alloc_text(FMREMAP,add_resource,remove_resource,free_resources)