source: trunk/dll/objcnr.c@ 1344

Last change on this file since 1344 was 1335, checked in by Steven Levine, 17 years ago

Ticket 26: Add exception handlers to all threads using xbeginthread

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
RevLine 
[159]1
2/***********************************************************************
3
4 $Id: objcnr.c 1335 2008-12-12 23:49:02Z stevenhl $
5
6 Object containers
7
8 Copyright (c) 1993-98 M. Kimes
[1335]9 Copyright (c) 2005, 2008 Steven H. Levine
[159]10
11 24 May 05 SHL Rework for CNRITEM.szSubject
[349]12 13 Jul 06 SHL Use Runtime_Error
[488]13 01 Sep 06 SHL Do not complain for normal cancel
[517]14 19 Oct 06 SHL Correct . and .. detect
[531]15 03 Nov 06 SHL Renames
[574]16 22 Mar 07 GKY Use QWL_USER
[751]17 01 Aug 07 SHL Rework to sync with CNRITEM mods
[756]18 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading)
[775]19 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
[783]20 13 Aug 07 SHL Avoid realloc - not needed; sanitize code
21 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat
[787]22 14 Aug 07 SHL Revert ProcessDir DosSleep to 0
[985]23 29 Feb 08 GKY Use xfree where appropriate
[1335]24 10 Dec 08 SHL Integrate exception handler support
[159]25
26***********************************************************************/
27
[907]28#include <stdlib.h>
29#include <string.h>
30#include <ctype.h>
[1335]31// #include <process.h> // _beginthread
[907]32
[2]33#define INCL_DOS
34#define INCL_WIN
[783]35#define INCL_DOSERRORS
[841]36#define INCL_LONGLONG
[2]37
[1188]38#include "fm3dll.h"
[1225]39#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
[1211]40#include "draglist.h" // Data declaration(s)
41#include "info.h" // Data declaration(s)
42#include "init.h" // Data declaration(s)
43#include "notebook.h" // Data declaration(s)
44#include "newview.h" // Data declarations
[2]45#include "fm3dlg.h"
46#include "fm3str.h"
[1163]47#include "errutil.h" // Dos_Error...
48#include "strutil.h" // GetPString
49#include "objcnr.h"
[1188]50#include "notify.h" // Notify
51#include "wrappers.h" // xDosFindNext
[1163]52#include "select.h" // ExpandAll
[1188]53#include "valid.h" // IsRoot
54#include "misc.h" // PostMsg
[1017]55#include "fortify.h"
[1335]56#include "excputil.h" // xbeginthread
[1017]57
[551]58typedef struct
59{
[2]60 CHAR *filename;
[551]61 HWND hwndCnr;
[2]62 CHAR *stopflag;
[551]63}
64DIRSIZE;
[2]65
[551]66typedef struct
67{
[2]68 CHAR *dirname;
[551]69 CHAR stopflag;
70 BOOL dying;
71 BOOL working;
72}
73TEMP;
[2]74
[349]75#pragma data_seg(DATA1)
[2]76
[349]77static PSZ pszSrcFile = __FILE__;
[2]78
[349]79static HWND objcnrwnd;
[2]80
[783]81static VOID ProcessDir(HWND hwndCnr,
[1335]82 CHAR *filename,
83 PCNRITEM pciParent,
84 CHAR *stopflag)
[349]85{
[551]86 CHAR maskstr[CCHMAXPATH], *endpath, *p;
[783]87 ULONG ulFindCnt, ulFindMax;
88 ULONG ulBufBytes;
[551]89 HDIR hdir;
[841]90 PFILEFINDBUF3L pffbArray;
[551]91 APIRET rc;
92 RECORDINSERT ri;
93 PCNRITEM pciP;
[783]94 HPOINTER hptr;
[2]95
[841]96 ulBufBytes = sizeof(FILEFINDBUF3L) * FilesToGet;
[783]97 pffbArray = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
98 if (!pffbArray)
[1163]99 return; // Error already reported
[551]100 strcpy(maskstr, filename);
101 if (maskstr[strlen(maskstr) - 1] != '\\')
102 strcat(maskstr, "\\");
[2]103 endpath = &maskstr[strlen(maskstr)];
[551]104 strcat(maskstr, "*");
[2]105 hdir = HDIR_CREATE;
[783]106 ulFindCnt = 1;
[838]107 rc = xDosFindFirst(filename, &hdir,
[1335]108 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
109 FILE_SYSTEM | FILE_HIDDEN | MUST_HAVE_DIRECTORY,
110 pffbArray, ulBufBytes, &ulFindCnt, FIL_STANDARDL);
[551]111 if (!rc)
[2]112 DosFindClose(hdir);
[783]113 // work around furshluginer FAT root bug
114 else if (IsRoot(filename))
115 rc = 0;
[2]116
[783]117 if ((!rc && (pffbArray->attrFile & FILE_DIRECTORY))) {
[731]118 pciP = WinSendMsg(hwndCnr,
[1335]119 CM_ALLOCRECORD,
120 MPFROMLONG(EXTRA_RECORD_BYTES),
121 MPFROMLONG(1));
[551]122 if (!pciP) {
[783]123 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, "CM_ALLOCRECORD");
[1039]124 free(pffbArray);
[2]125 return;
126 }
[730]127 pciP->pszFileName = xstrdup(filename, pszSrcFile, __LINE__);
[751]128 pciP->pszDispAttr = NullStr;
129 pciP->pszSubject = NullStr;
[762]130 pciP->pszLongName = NullStr;
[551]131 if (strlen(filename) < 4)
[751]132 pciP->pszDisplayName = pciP->pszFileName;
[2]133 else {
[730]134 p = strrchr(pciP->pszFileName, '\\');
[551]135 if (!p)
[1335]136 pciP->pszDisplayName = pciP->pszFileName;
[551]137 else if (*(p + 1))
[1335]138 p++;
[751]139 pciP->pszDisplayName = p;
[2]140 }
[751]141 pciP->rc.pszIcon = pciP->pszDisplayName;
[551]142 if (fForceUpper)
[730]143 strupr(pciP->pszFileName);
[551]144 else if (fForceLower)
[730]145 strlwr(pciP->pszFileName);
[2]146 pciP->rc.flRecordAttr |= CRA_RECORDREADONLY;
147 }
148 else {
[1039]149 free(pffbArray);
[783]150 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
[1335]151 GetPString(IDS_CANTFINDDIRTEXT), filename);
[2]152 return;
153 }
154
[783]155 hptr = WinLoadFileIcon(pciP->pszFileName, FALSE);
156 if (hptr)
157 pciP->rc.hptrIcon = hptr;
158
[1163]159 if (!pciP->rc.hptrIcon || pciP->rc.hptrIcon == hptrFile) /* OS/2 bug bug bug bug */
[2]160 pciP->rc.hptrIcon = hptrDir;
[783]161
[551]162 memset(&ri, 0, sizeof(RECORDINSERT));
163 ri.cb = sizeof(RECORDINSERT);
164 ri.pRecordOrder = (PRECORDCORE) CMA_END;
165 ri.pRecordParent = (PRECORDCORE) pciParent;
166 ri.zOrder = (USHORT) CMA_TOP;
[771]167 ri.cRecordsInsert = 1;
[551]168 ri.fInvalidateRecord = TRUE;
169 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD, MPFROMP(pciP), MPFROMP(&ri))) {
[1039]170 free(pffbArray);
[2]171 return;
172 }
173 hdir = HDIR_CREATE;
[551]174 if (!isalpha(*maskstr) || maskstr[1] != ':' || maskstr[2] != '\\' ||
175 ((driveflags[toupper(*maskstr) - 'A'] & DRIVE_REMOTE) && fRemoteBug))
[783]176 ulFindMax = 1;
[2]177 else
[783]178 ulFindMax = FilesToGet;
179 ulFindCnt = ulFindMax;
[838]180 rc = xDosFindFirst(maskstr, &hdir,
[1335]181 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
182 FILE_SYSTEM | FILE_HIDDEN | MUST_HAVE_DIRECTORY,
183 pffbArray, ulBufBytes, &ulFindCnt, FIL_STANDARDL);
[551]184 if (!rc) {
[841]185 PFILEFINDBUF3L pffbFile;
[551]186 ULONG x;
[2]187
[551]188 while (!rc) {
[783]189 pffbFile = pffbArray;
190 for (x = 0; x < ulFindCnt; x++) {
[1335]191 if (*stopflag)
192 break;
193 if ((pffbFile->attrFile & FILE_DIRECTORY) &&
194 // Skip . and ..
195 (pffbFile->achName[0] != '.' ||
196 (pffbFile->achName[1] &&
197 (pffbFile->achName[1] != '.' || pffbFile->achName[2])))) {
198 strcpy(endpath, pffbFile->achName);
199 ProcessDir(hwndCnr, maskstr, pciP, stopflag);
200 }
201 if (!pffbFile->oNextEntryOffset)
202 break;
203 pffbFile = (PFILEFINDBUF3L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
[783]204 } // for
[1163]205 DosSleep(0); // Let's others at same priority get some work done
[551]206 if (*stopflag)
[1335]207 break;
[783]208 ulFindCnt = ulFindMax;
[850]209 rc = xDosFindNext(hdir, pffbArray, ulBufBytes, &ulFindCnt, FIL_STANDARDL);
[783]210 } // while
[2]211 DosFindClose(hdir);
212 }
[783]213
214 if (rc && rc != ERROR_NO_MORE_FILES) {
215 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
[1335]216 GetPString(IDS_CANTFINDDIRTEXT), filename);
[783]217 }
218
[1039]219 free(pffbArray);
[551]220 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pciP),
[1335]221 MPFROM2SHORT(1, 0));
[2]222}
223
[551]224static VOID FillCnrsThread(VOID * args)
[349]225{
[551]226 HAB hab;
227 HMQ hmq;
[783]228 DIRSIZE *dirsize = (DIRSIZE *)args;
[2]229
[1038]230# ifdef FORTIFY
231 Fortify_EnterScope();
[1063]232# endif
[783]233 if (!dirsize) {
234 Runtime_Error(pszSrcFile, __LINE__, "no data");
[2]235 return;
[783]236 }
[2]237
238 DosError(FERR_DISABLEHARDERR);
239
240 hab = WinInitialize(0);
[551]241 if (hab) {
242 hmq = WinCreateMsgQueue(hab, 0);
243 if (hmq) {
244 WinCancelShutdown(hmq, TRUE);
245 ProcessDir(dirsize->hwndCnr, dirsize->filename, (PCNRITEM) NULL,
[1335]246 dirsize->stopflag);
[2]247 DosPostEventSem(CompactSem);
248 WinDestroyMsgQueue(hmq);
249 }
250 WinTerminate(hab);
251 }
[551]252 PostMsg(WinQueryWindow(dirsize->hwndCnr, QW_PARENT), UM_CONTAINER_FILLED,
[1335]253 MPVOID, MPVOID);
[1039]254 free(dirsize);
[1017]255# ifdef FORTIFY
256 Fortify_LeaveScope();
[1063]257# endif
[2]258}
259
[551]260MRESULT EXPENTRY ObjCnrDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
[349]261{
[2]262 TEMP *data;
263
[551]264 switch (msg) {
265 case WM_INITDLG:
266 if (objcnrwnd) {
267 Runtime_Error(pszSrcFile, __LINE__, "objcnrwnd set");
268 WinSetWindowPos(objcnrwnd, HWND_TOP, 0, 0, 0, 0,
[1335]269 SWP_RESTORE | SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER);
[551]270 WinDismissDlg(hwnd, 0);
271 break;
272 }
273 if (!mp2) {
274 Runtime_Error(pszSrcFile, __LINE__, "mp2 NULL");
275 WinDismissDlg(hwnd, 0);
276 break;
277 }
278 objcnrwnd = hwnd;
279 data = xmallocz(sizeof(TEMP), pszSrcFile, __LINE__);
280 if (!data) {
281 WinDismissDlg(hwnd, 0);
282 break;
283 }
[1009]284 data->dirname = (CHAR *)mp2;
[574]285 WinSetWindowPtr(hwnd, QWL_USER, (PVOID) data);
[551]286 if (*data->dirname)
287 WinSetDlgItemText(hwnd, OBJCNR_DIR, data->dirname);
288 {
289 DIRSIZE *dirsize;
[1063]290# ifdef FORTIFY
291 Fortify_EnterScope();
292# endif
[551]293 dirsize = xmalloc(sizeof(DIRSIZE), pszSrcFile, __LINE__);
294 if (!dirsize) {
[1335]295 WinDismissDlg(hwnd, 0);
296 break;
[2]297 }
[1009]298 dirsize->stopflag = (CHAR *)&data->stopflag;
[551]299 dirsize->filename = data->dirname;
300 dirsize->hwndCnr = WinWindowFromID(hwnd, OBJCNR_CNR);
[1335]301 if (xbeginthread(FillCnrsThread,
302 65536 * 8,
303 dirsize,
304 pszSrcFile,
305 __LINE__) == -1)
306 {
307 free(dirsize);
[1063]308# ifdef FORTIFY
[1335]309 Fortify_LeaveScope();
[1063]310# endif
[1335]311 WinDismissDlg(hwnd, 0);
312 break;
[349]313 }
[551]314 else
[1335]315 data->working = TRUE;
[551]316 }
317 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
318 break;
[2]319
[551]320 case UM_SETUP:
321 // WinEnableWindowUpdate(WinWindowFromID(hwnd,OBJCNR_CNR),FALSE);
322 {
323 CNRINFO cnri;
[2]324
[551]325 memset(&cnri, 0, sizeof(CNRINFO));
326 cnri.cb = sizeof(CNRINFO);
327 WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_QUERYCNRINFO,
[1335]328 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
[551]329 cnri.cyLineSpacing = 0;
330 cnri.cxTreeIndent = 12L;
331 cnri.pszCnrTitle = GetPString(IDS_WORKINGTEXT);
332 cnri.flWindowAttr = CV_TREE | CV_FLOW |
[1335]333 CA_CONTAINERTITLE | CA_TITLESEPARATOR | CA_TREELINE;
[551]334 if (WinQueryWindowUShort(hwnd, QWS_ID) == QTREE_FRAME)
[1335]335 cnri.flWindowAttr |= CV_MINI;
[551]336 WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_SETCNRINFO, MPFROMP(&cnri),
[1335]337 MPFROMLONG(CMA_FLWINDOWATTR | CMA_LINESPACING |
338 CMA_CXTREEINDENT));
[551]339 }
340 return 0;
[2]341
[551]342 case UM_CONTAINER_FILLED:
343 WinSetDlgItemText(hwnd, OBJCNR_NOTE, NullStr);
[2]344// WinEnableWindowUpdate(WinWindowFromID(hwnd,OBJCNR_CNR),TRUE);
[551]345 WinSendDlgItemMsg(hwnd, OBJCNR_CNR, CM_INVALIDATERECORD, MPVOID,
[1335]346 MPFROM2SHORT(0, CMA_ERASE | CMA_INVALIDATE));
[551]347 data = INSTDATA(hwnd);
348 if (data) {
349 data->working = FALSE;
350 if (data->dying)
[1335]351 WinDismissDlg(hwnd, 0);
[551]352 {
[1335]353 PCNRITEM pci;
354 USHORT id;
[2]355
[1335]356 id = WinQueryWindowUShort(hwnd, QWS_ID);
357 pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, OBJCNR_CNR,
358 CM_QUERYRECORD,
359 MPVOID,
360 MPFROM2SHORT(CMA_FIRST,
361 CMA_ITEMORDER));
362 if (pci && (INT) pci != -1) {
363 ExpandAll(WinWindowFromID(hwnd, OBJCNR_CNR), TRUE, pci);
364 if (id == QTREE_FRAME)
365 pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, OBJCNR_CNR,
366 CM_QUERYRECORD,
367 MPFROMP(pci),
368 MPFROM2SHORT(CMA_FIRSTCHILD,
369 CMA_ITEMORDER));
370 }
371 if ((!pci || (INT) pci == -1) && id == QTREE_FRAME) {
372 Notify(GetPString(IDS_NODIRSUNDERTEXT));
373 WinDismissDlg(hwnd, 0);
374 break;
375 }
[2]376 }
[551]377 }
378 return 0;
[2]379
[551]380 case WM_CONTROL:
381 switch (SHORT1FROMMP(mp1)) {
382 case OBJCNR_CNR:
383 if (SHORT2FROMMP(mp1) == CN_ENTER) {
[2]384
[1335]385 PCNRITEM pci = (PCNRITEM) ((PNOTIFYRECORDENTER) mp2)->pRecord;
[2]386
[1335]387 if (pci && (INT) pci != -1)
388 WinSendDlgItemMsg(hwnd, DID_OK, BM_CLICK, MPVOID, MPVOID);
[2]389 }
[551]390 break;
391 }
392 return 0;
[2]393
[551]394 case WM_COMMAND:
395 switch (SHORT1FROMMP(mp1)) {
396 case IDM_HELP:
397 if (hwndHelp) {
[2]398
[1335]399 USHORT id;
[2]400
[1335]401 id = WinQueryWindowUShort(hwnd, QWS_ID);
[2]402
[1335]403 if (id == QTREE_FRAME)
404 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
405 MPFROM2SHORT(HELP_QUICKTREE, 0),
406 MPFROMSHORT(HM_RESOURCEID));
407 else
408 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
409 MPFROM2SHORT(HELP_OBJECTPATH, 0),
410 MPFROMSHORT(HM_RESOURCEID));
[551]411 }
412 break;
[2]413
[551]414 case OBJCNR_DESKTOP:
415 case DID_OK:
416 data = INSTDATA(hwnd);
417 if (data) {
[2]418
[1335]419 PCNRITEM pci;
[2]420
[1335]421 if (data->working) {
422 Runtime_Error(pszSrcFile, __LINE__, "working unexpected");
423 break;
424 }
425 if (SHORT1FROMMP(mp1) == OBJCNR_DESKTOP) {
426 WinDismissDlg(hwnd, 2);
427 break;
428 }
429 pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, OBJCNR_CNR,
430 CM_QUERYRECORDEMPHASIS,
431 MPFROMLONG(CMA_FIRST),
432 MPFROMSHORT(CRA_CURSORED));
433 if (pci && (INT) pci != -1)
434 strcpy(data->dirname, pci->pszFileName);
435 WinDismissDlg(hwnd, 1);
[2]436 }
[551]437 break;
[2]438
[551]439 case DID_CANCEL:
[2]440 data = INSTDATA(hwnd);
[551]441 if (data) {
[1335]442 if (data->working) {
443 data->dying = (CHAR)TRUE;
444 data->stopflag = (CHAR)0xff;
445 break;
446 }
447 WinDismissDlg(hwnd, 0);
[551]448 }
[2]449 break;
[551]450 }
451 return 0;
452
453 case WM_DESTROY:
454 objcnrwnd = (HWND) 0;
455 data = INSTDATA(hwnd);
[1009]456 xfree(data, pszSrcFile, __LINE__);
[551]457 break;
[2]458 }
[551]459 return WinDefDlgProc(hwnd, msg, mp1, mp2);
[2]460}
[783]461
462#pragma alloc_text(OBJCNR,ProcessDir,FillCnrsThread,ObjCnrDlgProc)
Note: See TracBrowser for help on using the repository browser.