-
Notifications
You must be signed in to change notification settings - Fork 11
/
DataAccessMgr.c
6123 lines (5287 loc) · 141 KB
/
DataAccessMgr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
File: DataAccessMgr.c
Contains: C routines for the Data Access Manager (codename SnarfMan).
These internal routines have parallel names to the public
routines to avoid name conflicts (e.g. DBInit is SMInit).
Written by: Jeff Miller
Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<SM2> 11/19/92 RB Set ROMMapInsert to MapTrue just before doing some GetResource
calls so that we look in ROM first.
<30> 3/13/92 JSM Renamed this file DataAccessMgr.c from SnarfMan.c, keeping all
the old revisions.
<29> 7/15/91 dba get rid of MEMERR
<28> 6/12/91 JSM Completely delete about box code, which hasn't been used since
revision 19 anyway.
<27> 10/21/90 gbm Changing .hfileInfo to .hFileInfo again to match interfaces.
<27> 10/2/90 JAL Changed .hfileInfo to .hFileInfo to match interfaces.
<26> 9/12/90 JSM Fix bug when DBGetQueryResults is called async and DBState
returns noErr.
<25> 7/22/90 JSM rcDBNull is a valid return code to get from DBGetItem in
DBGetQueryResults, don't return an error in this case.
<24> 6/4/90 DC changed divide by 2 in FindHandler to right shift 1.
<23> 4/25/90 JSM Remove SMQuitDBPack, since it's no longer implemented.
<22> 4/24/90 JSM More code size reduction: Add CallStatusProc (common code for
most status function calls), calculate resListSize once in
SMGetNewQuery.
<21> 4/23/90 JSM Save and restore current GrafPort across call to qdef in
SMStartQuery.
<20> 4/10/90 JSM Make DBGetNewQuery return more errors, don't explicitly return
resNotFound unless ResErr is noErr, change back to .hfileInfo
(thanks, Dave).
<19> 4/2/90 JSM Even more code size reduction: remove about box and other
changes far too numerous to mention.
<18> 3/28/90 JSM Code size reduction: read ResErr and MemErr directly from
lomem.
<17> 3/13/90 JSM Change names of ResultsHandler routines to ResultHandler, add
support for new status function and result handler interface,
add support for new ResultsRecord format.
<16> 3/12/90 JSM Add support for completion routine in a separate resource.
<15> 3/9/90 JAL Changed .hfileInfo to .hFileInfo to match Files.h change.
<14> 2/26/90 JSM Don't HLock and HNoPurge package, now handled by PACKHelper.
<13> 2/23/90 JSM Add support for results handlers in separate resource.
<12> 2/22/90 JSM Add kDBStartQueryComplete, fix bug where AllDoneProc was never
cleaning up.
<11> 2/20/90 JSM Don't allow NULL query on DBStartQuery.
<10> 2/6/90 JSM Change rcDBCancel and rcDBStatusCancel to userCanceledErr, add
support for new status function message
kDBGetQueryResultsComplete.
<9> 2/5/90 JSM Look for ddevs in Extensions Folder.
<8> 1/31/90 JSM Fix return code bug in DBGetConnInfo.
<7> 1/18/90 JSM Use STR# from System file in default results handlers.
<6> 1/5/90 JSM Change default results handler for text to strip off trailing
spaces.
<5> 1/4/90 JSM Change some variable names in response to suggestions from
documentation.
<4> 12/28/89 dba Use quotes around the SnarfMan.h header file name, since the
file is a local header rather than part of public Interfaces.
<3> 12/22/89 JSM Use kDBLastColFlag in DBGetQueryResults.
<2> 12/20/89 JSM Cleanup for new build system.
<2.9> 12/7/89 JSM Added support for buffering partial rows in DBGetQueryResults.
<2.8> 11/21/89 JSM Set queryList and resList handles to NIL instead of empty
handles in DBGetNewQuery if no queries or resources in 'qrsc'.
<2.7> 11/15/89 JSM Always return sessID from ddev on DBInit, fix bug where calling
DBGetQueryResults async when no results causes problems.
<2.6> 11/7/89 JSM Added status functions, changed DBUnGetVal to DBUnGetItem, keep
track of ddev folder with vRefNum and dirID.
<2.5> 11/6/89 JSM Fixed bug with return codes from DBGetConnInfo.
<2.4> 11/1/89 JSM Fixed error handling for GetResource calls.
<2.3> 10/13/89 JSM Removed hack in DBGetQueryResults processing that worked around
a bug in CL/1 5.022.
<2.2> 10/6/89 JSM Updated to make SnarfMan a PACK.
<2.1> 9/18/89 JSM General cleanup and optimizing, fixed potential problem if null
parameters were passed in on some calls.
<2.0> 8/29/89 JSM Updated for new version 2 API.
<1.9> 8/7/89 JSM Added support for colLens in ResultsRecord, and kill and
results-to-text stuff (not quite done yet).
<1.8> 7/26/89 JSM Added support for ddev flags.
<1.7> 7/19/89 JSM Changed 'type' to 'dataType' in several places.
<1.6> 7/15/89 JSM Async stuff works now.
<1.5> 6/22/89 JSM Don't build ddev list at patch time, updated SMGetRow, messed
around with async some more.
<1.4> 6/9/89 JSM Added more stuff to support async, not quite working yet.
<1.3> 5/31/89 JSM No longer checks for rcDBReady, doesn't return rcDBSize, added
async support.
<1.2> 5/18/89 JSM Now return OSErr for everything, plus numerous other changes.
<1.1> 4/28/89 JSM Added lots o' new stuff, mostly high-level calls.
<1.0> 4/11/89 JSM Added to EASE for the first time.
*/
/* include our private header */
#include "DatabaseAccessPriv.h"
#include <SysEqu.h>
// #define DODPRINTF
/* I M P O R T S */
snarfGlobPtr GetGlobals();
snarfGlobPtr* GetGlobalsPtr();
void mymemclear(char *s, long size);
void CallCompletion(DBAsyncParmBlkPtr asyncPB);
/* E X P O R T S */
pascal OSErr SMInitDBPack(short version);
OSErr InstallDefaultHandlers(snarfGlobPtr glob);
pascal OSErr SMIdle();
OSErr SMOpen(ddevElemHndl ddevH);
OSErr SMClose(ddevElemHndl ddevH);
pascal OSErr SMInit(long *sessID, const Str63 ddevName, const Str255 host,
const Str255 user, const Str255 password, const Str255 connStr,
DBAsyncParmBlkPtr asyncPB);
pascal void SMInitComplete(ddevElemHndl ddevH, long *sessIDPtr,
long sessID, Boolean firstsess);
pascal OSErr SMEnd(long sessID, DBAsyncParmBlkPtr asyncPB);
OSErr SMEndComplete(snarfSessElemHndl snarf);
pascal OSErr SMGetConnInfo(long sessID, short sessNum, long *returnedID,
long *version, Str63 ddevName, Str255 host, Str255 user,
Str255 network, Str255 connStr, long *start, OSErr *state,
DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMGetSessionNum(long sessID, short *sessNum, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMSend(long sessID, char *text, short len, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMSendItem(long sessID, DBType dataType, short len, short places,
short flags, Ptr buffer, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMExec(long sessID, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMState(long sessID, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMGetErr(long sessID, long *err1, long *err2, Str255 item1,
Str255 item2, Str255 errorMsg, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMBreak(long sessID, Boolean abort, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMGetItem(long sessID, long timeout, DBType *dataType, short *len,
short *places, short *flags, Ptr buffer, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMUnGetItem(long sessID, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMGetNewQuery(short queryID, QueryHandle *query);
pascal OSErr SMDisposeQuery(QueryHandle query);
pascal OSErr SMStartQuery(long *sessID, QueryHandle query, statusPtr statusProc,
DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMGetQueryResults(long sessID, ResultsRecord *results,
long timeout, statusPtr statusProc, DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMKill(DBAsyncParmBlkPtr asyncPB);
pascal OSErr SMResultsToText(ResultsRecord *results, Handle *theText);
HandlerPtr GetCorrectResultHandler(DBType dataType);
pascal OSErr SMInstallResultHandler(DBType dataType, ProcPtr theHandler,
Boolean isSysHandler);
pascal OSErr SMRemoveResultHandler(DBType dataType);
pascal OSErr SMGetResultHandler(DBType dataType, ProcPtr *theHandler,
Boolean getSysHandler);
short FindHandler(DBType dataType);
OSErr InsertHandler(HandlerRecord *newRec);
OSErr RemoveHandler(short index);
OSErr SMGeneric(long snarfID, DBAsyncParmBlkPtr asyncPB,
DDEVParams *params);
OSErr InitDoneProc(DBAsyncParmBlkPtr myPB, asyncVarsPtr myVars);
OSErr SendDoneProc(DBAsyncParmBlkPtr myPB, asyncVarsPtr myVars);
OSErr ExecDoneProc(DBAsyncParmBlkPtr myPB, asyncVarsPtr myVars);
OSErr StateDoneProc(DBAsyncParmBlkPtr myPB, asyncVarsPtr myVars);
OSErr GetItemDoneProc(DBAsyncParmBlkPtr myPB, asyncVarsPtr myVars);
OSErr AllDoneProc(DBAsyncParmBlkPtr myPB, asyncVarsPtr myVars);
void BuildDDEVList(ddevElemHndl *root);
void ClearDDEVList(ddevElemHndl root);
void PurgeDDEVList(ddevElemHndl *root);
void AddDDEVFile(const Str255 fname, short vRefNum, long dirID,
ddevElemHndl *root);
ddevElemHndl FindAndBuildDDEV(char *name, ddevElemHndl *rootPtr);
ddevElemHndl FindDDEV(char *name, ddevElemHndl root);
OSErr OpenDDEVFile(ddevElemHndl ddevH, short *refNum);
OSErr CallDDEV(ddevElemHndl ddevH, DDEVParams *params);
long GetUniqueSnarfID(snarfSessElemHndl root);
snarfSessElemHndl FindSnarfID(long id, snarfSessElemHndl root);
long ConvertSessIDToSnarfID(long sessID, ddevElemHndl ddevH);
void InsertSessionCell(sessElemHndl *root, sessElemHndl cell);
void InsertSnarfCell(snarfSessElemHndl *root, snarfSessElemHndl cell);
DBAsyncParmBlkPtr MakePB(DDEVParamsPtr params, DBAsyncParmBlkPtr asyncPB);
pascal void InsertPB(DBAsyncParmBlkPtr asyncPB);
pascal void RemovePB(DBAsyncParmBlkPtr asyncPB);
DBAsyncParmBlkPtr FindAppPB(DBAsyncParmBlkPtr appPB);
void GetDDEVFolder(short *vRefNum, long *dirID);
OSErr GrowResultsRecord(ResultsRecord *results, short len,
Boolean inFirstRow);
OSErr SetupResults(long sessID, snarfSessElemHndl *snarfPtr,
ResultsRecord *results, ResultsRecord **oldResultsPtr,
long *currOffset, short *currCol);
pascal void DisposeResultsRecord(ResultsRecord *results);
OSErr InitResultsRecord(ResultsRecord *results, Boolean inSysHeap);
OSErr CallStatusProc(statusPtr statusProc, short message, OSErr rc);
pascal void MyHLock(Handle h, char *state);
/*FORM_FEED*/
/*
*
* OBJECT: SMInitDBPack
*
* DESCRIPTION: Called to initialize SnarfMan by each application. The version
* number is implicitly passed in by the routine definition in
* DatabaseAccess.h. This number is compared to the version in the
* PACK resource. The first time this routine is called, it
* allocates space for globals and installs default result handlers.
*
* INPUTS: version: Version as defined in DatabaseAccess.h.
*
* OUTPUTS: None.
*
* RETURNS: rcDBWrongVersion
* Errors from NewPtrSysClear and InstallDefaultHandlers.
*
* MODIFICATIONS:
* 10-03-89 JSM - Created.
*
* Copyright Apple Computer, Inc. 1989
* All rights reserved.
*
*/
pascal OSErr
SMInitDBPack(short version)
{
register snarfGlobPtr *globPtr;
register snarfGlobPtr glob;
register short rc;
Handle resH;
PackHeaderHndl thePack;
/* compare version numbers */
thePack = DataAccessMgrPack;
if ((**thePack).version != version)
return(rcDBWrongVersion);
/*
For now, we always stay locked down.
Hopefully, we'll be more intelligent about this in
the future.
We no longer need to do this, PACKHelper takes care of it!
*/
// HNoPurge((Handle)thePack);
// HLock((Handle)thePack);
/* see if we need to allocate globals */
globPtr = GetGlobalsPtr();
rc = noErr;
if (*globPtr == NULL)
{
/* allocate a cleared pointer in the system heap for globals */
*globPtr = (snarfGlobPtr)NewPtrSysClear(sizeof(snarfGlob));
rc = MemError();
if (rc == noErr)
{
glob = *globPtr;
/* build the list of installed ddevs */
/*
It turns out we can't do this at patch time because there is
no International Utilities package available yet (AddDDEVFile
calls IUCompStr). So, it gets done at the first DBInit call.
BuildDDEVList(&((*globPtr)->ddevRoot));
*/
/*
Load the standard completion routine.
We have to keep this separate so it doesn't
get unlocked and/or purged at the wrong
time by PACKHelper.
*/
*((short*) RomMapInsert) = mapTrue;
resH = GetResource(COMPCODERESTYPE, COMPCODERESID);
if (resH != NULL)
{
/* detach it */
DetachResource(resH);
/* resource should have locked bit set */
/* save this handle in the globals */
/* we may purge this someday */
glob->completionRes = resH;
}
else
{
/* couldn't get specified 'proc' resource */
if ((rc = RESERR) == noErr)
rc = resNotFound;
/* we better not continue, so get rid of the globals */
DisposPtr((Ptr)glob);
*globPtr = NULL;
}
if (rc == noErr)
{
/* install default result handlers */
rc = InstallDefaultHandlers(glob);
/* even if this fails, it isn't a fatal error, so leave globals around */
}
}
}
return(rc);
} /* SMInitDBPack() */
/*FORM_FEED*/
/*
*
* OBJECT: InstallDefaultHandlers
*
* DESCRIPTION: Called by SMInitDBPack to install the default system result handlers.
* Reads the 'rtt#' resource and 'proc' resource containing the handlers,
* then calls DBInstallResultHandler for each one.
*
* INPUTS: glob: Pointer to globals.
*
* OUTPUTS: None.
*
* RETURNS: resNotFound
* Errors from NewHandleSys and DBInstallResultHandler.
*
* MODIFICATIONS:
* 03-29-90 JSM - Created.
*
* Copyright Apple Computer, Inc. 1990
* All rights reserved.
*
*/
OSErr
InstallDefaultHandlers(snarfGlobPtr glob)
{
register OSErr rc;
register Handle resH;
register Ptr resP;
register short numTypes;
register short handlerID;
Handle handlerH;
ProcPtr p;
/* short numHandlers; */
/* allocate empty array of result handlers */
glob->handlers = (HandlerRecordHandle)NewHandleSys(NULL);
rc = MemError();
/*
Install the default handlers.
These live in a separate 'proc' resource so it can stay locked
down in one place all the time. The 'rtt#' resource specifies
which handlers we have. It looks like:
short numHandlers; number of 'proc' resources
we only support one now
For each 'proc':
short id; id of 'proc'
short numTypes; number of types handled by this 'proc'
DBType typeArray[numTypes]; types handled by this 'proc'
*/
if (rc == noErr)
{
/* get the 'rtt#' */
*((short*) RomMapInsert) = mapTrue;
resH = GetResource(RTTLISTRESTYPE, RTTLISTID);
if (resH != NULL)
{
HLock(resH);
resP = *resH;
/* get number of 'proc' resources */
/* we support one and only one for now */
/* numHandlers = *((short*)resP); */
resP += sizeof(short);
/* get the id of this 'proc' */
handlerID = *((short*)resP);
resP += sizeof(short);
/* get number of types supported by this 'proc' */
numTypes = *((short*)resP);
resP += sizeof(short);
/* load in 'proc' */
*((short*) RomMapInsert) = mapTrue;
handlerH = GetResource(RTTCODERESTYPE, handlerID);
if (handlerH != NULL)
{
/* detach it */
DetachResource(handlerH);
/* resource should have locked bit set */
/* save this handle in the globals */
/* we may purge this someday */
glob->handlerRes = handlerH;
/* make sure we're 32 bit clean */
p = (ProcPtr)StripAddress(*handlerH);
/* now, install it as a result handler for specified types */
while((numTypes != 0) && (rc == noErr))
{
/* install handler for current type */
rc = DBInstallResultHandler(*((DBType*)resP), p, true);
resP += sizeof(DBType);
numTypes--;
}
}
else
{
/* couldn't get specified 'proc' resource */
if ((rc = RESERR) == noErr)
rc = resNotFound;
}
/* get rid of 'rtt#' (no need to unlock it) */
ReleaseResource(resH);
}
/* we could put an else here if 'rtt#' resource not found, but it's not a fatal error */
}
return(rc);
} /* InstallDefaultHandlers() */
/*FORM_FEED*/
/*
*
* OBJECT: SMIdle
*
* DESCRIPTION: Called every time SystemTask called. Sends DBIdle message to any
* ddev with active sessions. Also checks global list of asynchronous
* parameter blocks to see if it needs to perform a task that cannot be
* done at interrupt time.
*
* INPUTS: None.
*
* OUTPUTS: None.
*
* RETURNS: Nothing.
*
* MODIFICATIONS:
* 04-05-89 JSM - Created.
*
* Copyright Apple Computer, Inc. 1989
* All rights reserved.
*
*/
pascal OSErr
SMIdle()
{
register ddevElemHndl ddevH;
register DBAsyncParmBlkPtr myPB;
register asyncVarsPtr myVars;
register short rc;
snarfGlobPtr glob;
DBAsyncParmBlkPtr appPB, nextPB;
DDEVParams params;
glob = GetGlobals();
/* get first ddev in list */
ddevH = glob->ddevRoot;
/****************************************/
/* send idle messages to all open ddevs */
/****************************************/
while (ddevH != NULL)
{
/* see if this ddev has any open sessions */
if ((**ddevH).sessRoot != NULL)
{
/* yes, send it an idle message */
/* fill in parameter block for DBIdle */
ClearParams(params);
params.message = kDBIdle;
/* ignore any errors */
(void)CallDDEV(ddevH, ¶ms);
}
/* get next ddev in list */
ddevH = (**ddevH).next;
}
/***************************************/
/* go through list of parameter blocks */
/***************************************/
myPB = glob->pbRoot;
while (myPB != NULL)
{
myVars = (asyncVarsPtr)myPB->reserved;
/* get next pb here in case we dispose of the current one */
nextPB = myVars->next;
if (!(myVars->executing))
{
/* current pb is done executing */
if (!myVars->highlevel)
{
/********************************/
/* low-level call has completed */
/********************************/
/* have to return parameters and do additional
cleanup for some calls */
switch (myVars->currAction)
{
case kDBInit:
/* finish up using common code */
SMInitComplete(myVars->ddevH, myVars->sessIDPtr,
myVars->params->sessID, myVars->firstsess);
break;
case kDBEnd:
if (myPB->result == noErr)
{
/* session ended OK */
/* finish up using common code */
myPB->result = SMEndComplete(myVars->snarf);
}
break;
case kDBGetConnInfo:
/* return returnedID, version, start, and state */
/*
Note that the returnedID in the DDEVParams is the
ddev's session ID, which we have to convert
to a global Snarf ID.
*/
if (myVars->returnedIDPtr != NULL)
{
if (myPB->result == noErr) /* fix for bug DSL-008 */
{
/* ddev thinks it returned a valid session ID */
*(myVars->returnedIDPtr) =
ConvertSessIDToSnarfID(myVars->params->returnedID,
myVars->ddevH);
if (*(myVars->returnedIDPtr) == NULL)
{
/*
The session ID returned by the ddev does
not match any of the active sessions we
have for it. Hopefully, this should
never happen.
*/
myPB->result = rcDBBadSessID;
}
}
}
if (myVars->versionPtr != NULL)
{
*(myVars->versionPtr) = myVars->params->version;
}
if (myVars->startPtr != NULL)
{
*(myVars->startPtr) = myVars->params->start;
}
if (myVars->statePtr != NULL)
{
*(myVars->statePtr) = myVars->params->state;
}
break;
case kDBGetSessionNum:
/* return sessNum */
*(myVars->sessNumPtr) = myVars->params->sessNum;
break;
case kDBGetErr:
/* return err1 and err2 */
if (myVars->err1Ptr != NULL)
{
*(myVars->err1Ptr) = myVars->params->err1;
}
if (myVars->err2Ptr != NULL)
{
*(myVars->err2Ptr) = myVars->params->err2;
}
break;
case kDBGetItem:
/* return dataType, len, places, and flags */
if (myVars->dataTypePtr != NULL)
{
*(myVars->dataTypePtr) = myVars->params->dataType;
}
if (myVars->lenPtr != NULL)
{
*(myVars->lenPtr) = myVars->params->len;
}
if (myVars->placesPtr != NULL)
{
*(myVars->placesPtr) = myVars->params->places;
}
if (myVars->flagsPtr != NULL)
{
*(myVars->flagsPtr) = myVars->params->flags;
}
break;
}
/* copy result into application's parameter block */
appPB = myVars->asyncPB;
appPB->result = myPB->result;
/* remove pb from list */
RemovePB(myPB);
/* call application's completion routine, if any */
if (appPB->completionProc != NULL)
{
/* have to use assembly glue to get pb into A0 */
CallCompletion(appPB);
}
}
else
{
/***********************************************************/
/* high-level call has completed, call appropriate routine */
/***********************************************************/
switch (myVars->currAction)
{
/* DBStartQuery actions */
case kDBInit:
rc = InitDoneProc(myPB, myVars);
break;
case kDBSend:
rc = SendDoneProc(myPB, myVars);
break;
case kDBExec:
rc = ExecDoneProc(myPB, myVars);
/* always go to done from here */
rc = AllDoneProc(myPB, myVars);
break;
/* DBGetQueryResults actions */
case kDBState:
rc = StateDoneProc(myPB, myVars);
break;
case kDBGetItem:
rc = GetItemDoneProc(myPB, myVars);
break;
/* all processing complete */
/* this is only from GetItemDoneProc */
case kAllDone:
/* let AllDoneProc know what to clean up */
myVars->currAction = kDBGetItem;
rc = AllDoneProc(myPB, myVars);
break;
} /* switch (myVars->currAction) */
if (rc != noErr)
{
/* error occurred someplace, so we're done */
(void)AllDoneProc(myPB, myVars);
}
} /* if (!myVars->highlevel) */
} /* if (!(myVars->executing)) */
myPB = nextPB;
} /* while (myPB != NULL) */
return(noErr);
} /* SMIdle() */
/*FORM_FEED*/
/*
*
* OBJECT: SMOpen
*
* DESCRIPTION: Called to send a DBOpen to ddev when first session is initiated.
* This is always a synchronous call. Opens file, gets and detaches
* resource, calls ddev, and closes file.
*
* INPUTS: ddevH: Handle to ddevElem with info.
*
* OUTPUTS: None.
*
* RETURNS: Errors from opening resource file, getting ddev resource,
* detaching ddev resource, and CallDDEV.
*
* MODIFICATIONS:
* 05-23-89 JSM - Created.
*
* Copyright Apple Computer, Inc. 1989
* All rights reserved.
*
*/
OSErr
SMOpen(ddevElemHndl ddevH)
{
register DDEVPtr *ddevRes;
register OSErr rc;
register short currResFile;
short currVol, refNum = -1;
short vRefNum;
long dirID;
DDEVParams params;
WDPBRec pb;
/* save current file */
currResFile = CURMAP;
/* open ddev file */
rc = OpenDDEVFile(ddevH, &refNum);
if (rc == noErr)
{
/* file open, get the resource */
ddevRes = (DDEVPtr*)Get1Resource(DDEVRESTYPE, kDDEVID);
if (ddevRes != NULL)
{
/* detach ddev resource */
DetachResource((Handle)ddevRes);
rc = RESERR;
}
else
{
/* couldn't get ddev */
/* note that GetResource does not set ResErr for resNotFound! */
if ((rc = RESERR) == noErr)
rc = resNotFound;
}
if (rc == noErr)
{
/* lock down ddev code always */
HLock((Handle)ddevRes);
/* save handle to ddev in ddevH */
(**ddevH).ddev = ddevRes;
/* save old volume and set to ddev's volume */
(void)GetVol(NULL, &currVol);
/********************************************/
/* ¥WARNING¥ ¥WARNING¥ ¥WARNING¥ ¥WARNING¥ */
/* */
/* The following is kind of bogus, but it */
/* is probably better than doing an HSetVol.*/
/* We need a working directory, though, to */
/* do a normal SetVol. Darin suggested not */
/* closing it when we're done. */
/* */
/* ¥WARNING¥ ¥WARNING¥ ¥WARNING¥ ¥WARNING¥ */
/********************************************/
/* get vRefNum and dirID of ddev folder */
GetDDEVFolder(&vRefNum, &dirID);
/* open a working directory */
pb.ioCompletion = 0L;
pb.ioNamePtr = 0L;
pb.ioVRefNum = vRefNum;
pb.ioWDDirID = dirID;
pb.ioWDProcID = 'ERIK'; /* Darin says use this */
rc = PBOpenWD(&pb, false);
if (rc == noErr)
{
/* opened working directory */
(void)SetVol(NULL, pb.ioVRefNum);
/* set up parameters for open */
ClearParams(params);
params.message = kDBOpen;
/* call ddev - DBOpen */
rc = CallDDEV(ddevH, ¶ms);
/* restore current volume */
(void)SetVol(NULL, currVol);
}
}
if ((rc != noErr) && (ddevRes != NULL))
{
/* error opening ddev, dispose of everything */
/* dispose of ddev code (no need to unlock it) */
DisposHandle((Handle)ddevRes);
(**ddevH).ddev = NULL;
/* no more storage */
(**ddevH).ddevStorage = NULL;
}
}
/* clean up */
if (refNum != -1)
CloseResFile(refNum);
UseResFile(currResFile);
return(rc);
} /* SMOpen() */
/*FORM_FEED*/
/*
*
* OBJECT: SMClose
*
* DESCRIPTION: Called to send a DBClose to ddev when last session has ended.
* Disposes of ddev code. This is always a synchronous call.
*
* INPUTS: ddevH: Handle to ddevElem with info.
*
* OUTPUTS: None.
*
* RETURNS: Return codes from CallDDEV, DisposHandle.
*
* MODIFICATIONS:
* 05-23-89 JSM - Created.
*
* Copyright Apple Computer, Inc. 1989
* All rights reserved.
*
*/
OSErr
SMClose(ddevElemHndl ddevH)
{
register short rc;
DDEVParams params;
ClearParams(params);
params.message = kDBClose;
/* call ddev - DBClose */
rc = CallDDEV(ddevH, ¶ms);
/* dispose of ddev code (no need to unlock it) */
DisposHandle((Handle)(**ddevH).ddev);
(**ddevH).ddev = NULL;
/* no more storage */
(**ddevH).ddevStorage = NULL;
/* report errors from DBClose first before MemError */
if (rc == noErr)
{
/* DBClose OK, so report any error from DisposHandle */
rc = MemError();
}
return(rc);
} /* SMClose() */
/*FORM_FEED*/
/*
*
* OBJECT: SMInit
*
* DESCRIPTION: DBInit routine. Searches for specified ddev, opens it if
* this is the first session for it (sending it a DBOpen message),
* sends it a DBInit message, and calls common code which inserts a
* new session and snarf id into the session and snarf id lists.
*
* INPUTS: sessID: Pointer to variable for session ID.
* ddevName: Corresponds to 'STR ' 128 in ddev.
* host: Host name.
* user: User name.
* passwd: Password.
* connStr: Connection string.
* asyncPB: Pointer to asynchronous parameter block.
*
* OUTPUTS: sessID: Pointer to filled in session ID.
*
* RETURNS: rcDBBadDDEV
* rcDBAsyncNotSupp
* Errors from SMOpen and CallDDEV.
*
* MODIFICATIONS:
* 03-23-89 JSM - Created.
*
* Copyright Apple Computer, Inc. 1989
* All rights reserved.
*
*/
pascal OSErr
SMInit(long *sessID, const Str63 ddevName, const Str255 host,
const Str255 user, const Str255 password, const Str255 connStr, DBAsyncParmBlkPtr asyncPB)
{
register ddevElemHndl ddevH;
register asyncVarsPtr myVars;
register OSErr rc = noErr;
register Boolean firstsess;
snarfGlobPtr glob;
DBAsyncParmBlkPtr myPB;
DDEVParams params;
/* assume no session will come up */
*sessID = 0;
glob = GetGlobals();
/* look for ddevElem with specified ddevName, rebuilding list if necessary */
ddevH = FindAndBuildDDEV((char*)ddevName, &(glob->ddevRoot));
if (ddevH == NULL)
{
/* bad ddev name */
rc = rcDBBadDDEV;
}
if (rc == noErr)
{
/* see if ddev code loaded, if not, then it needs a DBOpen call */
firstsess = ((**ddevH).ddev == NULL);
if (firstsess)
{
/* special case - check for async here so we don't send open */
if (asyncPB && !(**ddevH).canAsync)
{
/* ddev doesn't support async, but DBInit called async */
rc = rcDBAsyncNotSupp;
}
if (rc == noErr)
{
/* call ddev with open message */
rc = SMOpen(ddevH);
}
}
if (rc == noErr)
{
/* fill in parameter block for DBInit */
ClearParams(params);
params.message = kDBInit;
params.host = host;
params.user = user;
params.password = password;
params.connStr = connStr;
/* check for asynchronous call */
if (asyncPB)
{
/* we have to set up our own parameter block */
myPB = MakePB(¶ms, asyncPB);
myVars = (asyncVarsPtr)myPB->reserved;
/* keep track if first session for ddev */
myVars->firstsess = firstsess;
/* keep track of session ID */
myVars->sessIDPtr = sessID;