Added PSharedptr class
[pwlib.git] / src / ptlib / msos / mswin.cxx
blob02b92fc97b9fbb3ab704d4b5f5821ff7967878aa
1 /*
2 * mswin.cxx
4 * General class implementations for 16 bit Windows.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
29 * $Log$
30 * Revision 1.18 2001/08/07 03:20:39 robertj
31 * Fixed close of DLL so flagged as closed, thanks Stefan Ditscheid.
33 * Revision 1.17 1998/09/24 03:30:51 robertj
34 * Added open software license.
36 * Revision 1.16 1996/02/15 14:55:02 robertj
37 * Win16 compatibility
39 * Revision 1.15 1996/01/28 02:55:33 robertj
40 * WIN16 support.
42 * Revision 1.14 1995/12/10 11:58:37 robertj
43 * Added WIN32 registry support for PConfig objects.
45 * Revision 1.13 1995/08/24 12:40:52 robertj
46 * Changed PChannel so not a PContainer.
48 * Revision 1.12 1995/07/02 01:24:45 robertj
49 * Added running of hidden VM for DOS program in PPipeChannel.
51 * Revision 1.11 1995/06/17 00:59:23 robertj
52 * Moved PPipeChannel::Execute from common dos/windows to individual files.
54 * Revision 1.10 1995/03/12 05:00:06 robertj
55 * Re-organisation of DOS/WIN16 and WIN32 platforms to maximise common code.
56 * Used built-in equate for WIN32 API (_WIN32).
58 * Revision 1.9 1995/01/09 12:28:00 robertj
59 * Added implementation for PConfig::Environment
61 * Revision 1.8 1994/10/23 05:41:29 robertj
62 * Fixed config file bugs.
64 * Revision 1.7 1994/08/22 00:18:02 robertj
65 * Fixed bug in serial comms timers.
67 * Revision 1.6 1994/08/04 13:24:27 robertj
68 * Added DCB so can set paraemters on closed channel.
70 * Revision 1.5 1994/07/27 06:00:10 robertj
71 * Backup
73 * Revision 1.4 1994/07/21 12:35:18 robertj
74 * *** empty log message ***
76 * Revision 1.3 1994/07/17 11:01:04 robertj
77 * Ehancements, implementation, bug fixes etc.
79 * Revision 1.2 1994/07/02 03:18:09 robertj
80 * Multi-threading implementation.
82 * Revision 1.1 1994/06/25 12:13:01 robertj
83 * Initial revision
85 // Revision 1.1 1994/04/01 14:39:35 robertj
86 // Initial revision
90 #include "ptlib.h"
91 #include <errno.h>
92 #include <fcntl.h>
94 #include <stdresid.h>
97 extern "C" HINSTANCE _hInstance;
100 ///////////////////////////////////////////////////////////////////////////////
101 // PTime
103 PString PTime::GetTimeSeparator()
105 PString str;
106 GetProfileString("intl", "sTime", ":", str.GetPointer(100), 99);
107 str.MakeMinimumSize();
108 return str;
112 BOOL PTime::GetTimeAMPM()
114 return GetProfileInt("intl", "iTime", 0) != 0;
118 PString PTime::GetTimeAM()
120 PString str;
121 GetProfileString("intl", "s1159", "am", str.GetPointer(100), 99);
122 str.MakeMinimumSize();
123 return str;
127 PString PTime::GetTimePM()
129 PString str;
130 GetProfileString("intl", "s2359", "pm", str.GetPointer(100), 99);
131 str.MakeMinimumSize();
132 return str;
136 PString PTime::GetDayName(Weekdays dayOfWeek, NameType type)
138 static const char * const weekdays[] = {
139 "Sunday", "Monday", "Tuesday", "Wednesday",
140 "Thursday", "Friday", "Saturday"
142 static const char * const abbrev_weekdays[] = {
143 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
145 PString str;
146 if (LoadString(_hInstance, dayOfWeek+
147 (type != FullName ? PSTD_ID_STR_ABBREV_WEEKDAYS : PSTD_ID_STR_WEEKDAYS),
148 str.GetPointer(100), 99) == 0)
149 return (type != FullName ? abbrev_weekdays : weekdays)[dayOfWeek];
150 str.MakeMinimumSize();
151 return str;
155 PString PTime::GetDateSeparator()
157 PString str;
158 GetProfileString("intl", "sDate", "-", str.GetPointer(100), 99);
159 str.MakeMinimumSize();
160 return str;
164 PString PTime::GetMonthName(Months month, NameType type)
166 static const char * const months[] = { "",
167 "January", "February", "March", "April", "May", "June",
168 "July", "August", "September", "October", "November", "December"
170 static const char * const abbrev_months[] = {
171 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
172 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
174 PString str;
175 if (LoadString(_hInstance, month+
176 (UINT)(type != FullName ? PSTD_ID_STR_ABBREV_MONTHS : PSTD_ID_STR_MONTHS),
177 str.GetPointer(100), 99) == 0)
178 return (type != FullName ? abbrev_months : months)[month];
179 str.MakeMinimumSize();
180 return str;
184 PTime::DateOrder PTime::GetDateOrder()
186 return (DateOrder)GetProfileInt("intl", "iDate", 0);
190 BOOL PTime::IsDaylightSavings()
192 return FALSE;
196 int PTime::GetTimeZone(TimeZoneType type)
198 return 0;
202 PString PTime::GetTimeZoneString(TimeZoneType type)
204 return "";
208 ///////////////////////////////////////////////////////////////////////////////
209 // PSerialChannel
211 void PSerialChannel::Construct()
213 char str[50];
214 strcpy(str, "com1");
215 GetProfileString("ports", str, "9600,n,8,1,x", &str[5], sizeof(str)-6);
216 str[4] = ':';
217 if (!BuildCommDCB(str, &deviceControlBlock)) {
218 osError = EINVAL;
219 lastError = BadParameter;
224 PString PSerialChannel::GetName() const
226 if (IsOpen())
227 return psprintf("COM%i", os_handle+1);
229 return PString();
233 BOOL PSerialChannel::IsReadBlocked(PObject * obj)
235 PSerialChannel & chan = *(PSerialChannel *)PAssertNULL(obj);
236 COMSTAT stat;
237 GetCommError(chan.os_handle, &stat);
238 return stat.cbInQue <= 0 &&
239 (chan.readTimeout == PMaxTimeInterval || chan.readTimer.IsRunning());
243 BOOL PSerialChannel::Read(void * buf, PINDEX len)
245 lastReadCount = 0;
247 if (!IsOpen()) {
248 PThread::Yield();
249 osError = EBADF;
250 lastError = NotOpen;
251 return FALSE;
254 if (readTimeout != PMaxTimeInterval)
255 readTimer = readTimeout;
256 if (IsReadBlocked(this))
257 PThread::Current()->Block(&PSerialChannel::IsReadBlocked, this);
259 lastReadCount = ReadComm(os_handle, buf, len);
260 if (lastReadCount > 0)
261 return TRUE;
263 COMSTAT stat;
264 GetCommError(os_handle, &stat);
265 osError = EFAULT;
266 lastReadCount = -lastReadCount;
267 return lastReadCount > 0;
271 BOOL PSerialChannel::IsWriteBlocked(PObject * obj)
273 PSerialChannel & chan = *(PSerialChannel *)PAssertNULL(obj);
274 COMSTAT stat;
275 GetCommError(chan.os_handle, &stat);
276 return stat.cbOutQue >= OutputQueueSize &&
277 (chan.writeTimeout == PMaxTimeInterval || chan.writeTimer.IsRunning());
281 BOOL PSerialChannel::Write(const void * buf, PINDEX len)
283 lastWriteCount = 0;
285 if (!IsOpen()) {
286 osError = EBADF;
287 lastError = NotOpen;
288 return FALSE;
291 if (writeTimeout != PMaxTimeInterval)
292 writeTimer = writeTimeout;
293 if (IsWriteBlocked(this))
294 PThread::Current()->Block(&PSerialChannel::IsWriteBlocked, this);
296 lastWriteCount = WriteComm(os_handle, buf, len);
297 if (lastWriteCount <= 0) {
298 COMSTAT stat;
299 GetCommError(os_handle, &stat);
300 osError = EFAULT;
301 lastWriteCount = -lastWriteCount;
303 return lastWriteCount >= len;
307 BOOL PSerialChannel::Close()
309 if (!IsOpen()) {
310 osError = EBADF;
311 lastError = NotOpen;
312 return FALSE;
315 BOOL retVal = CloseComm(os_handle) == 0;
316 os_handle = -1;
317 return retVal;
321 BOOL PSerialChannel::SetCommsParam(DWORD speed, BYTE data, Parity parity,
322 BYTE stop, FlowControl inputFlow, FlowControl outputFlow)
324 if (IsOpen())
325 PAssert(GetCommState(os_handle, &deviceControlBlock) == 0,
326 POperatingSystemError);
328 switch (speed) {
329 case 0 :
330 break;
331 case 14400 :
332 deviceControlBlock.BaudRate = CBR_14400;
333 break;
334 case 19200 :
335 deviceControlBlock.BaudRate = CBR_19200;
336 break;
337 case 38400 :
338 deviceControlBlock.BaudRate = CBR_38400;
339 break;
340 case 56000 :
341 deviceControlBlock.BaudRate = CBR_56000;
342 break;
343 case 128000 :
344 deviceControlBlock.BaudRate = CBR_128000;
345 break;
346 case 256000 :
347 deviceControlBlock.BaudRate = CBR_256000;
348 break;
349 default :
350 if (speed > 9600) {
351 osError = EINVAL;
352 return FALSE;
354 deviceControlBlock.BaudRate = (UINT)speed;
357 if (data > 0)
358 deviceControlBlock.ByteSize = data;
360 switch (parity) {
361 case NoParity :
362 deviceControlBlock.Parity = NOPARITY;
363 break;
364 case OddParity :
365 deviceControlBlock.Parity = ODDPARITY;
366 break;
367 case EvenParity :
368 deviceControlBlock.Parity = EVENPARITY;
369 break;
370 case MarkParity :
371 deviceControlBlock.Parity = MARKPARITY;
372 break;
373 case SpaceParity :
374 deviceControlBlock.Parity = SPACEPARITY;
375 break;
377 switch (stop) {
378 case 1 :
379 deviceControlBlock.StopBits = ONESTOPBIT;
380 break;
381 case 2 :
382 deviceControlBlock.StopBits = TWOSTOPBITS;
383 break;
385 switch (inputFlow) {
386 case NoFlowControl :
387 deviceControlBlock.fRtsflow = FALSE;
388 deviceControlBlock.fInX = FALSE;
389 break;
390 case XonXoff :
391 deviceControlBlock.fRtsflow = FALSE;
392 deviceControlBlock.fInX = TRUE;
393 break;
394 case RtsCts :
395 deviceControlBlock.fRtsflow = TRUE;
396 deviceControlBlock.fInX = FALSE;
397 break;
400 switch (outputFlow) {
401 case NoFlowControl :
402 deviceControlBlock.fOutxCtsFlow = FALSE;
403 deviceControlBlock.fOutxDsrFlow = FALSE;
404 deviceControlBlock.fOutX = FALSE;
405 break;
406 case XonXoff :
407 deviceControlBlock.fOutxCtsFlow = FALSE;
408 deviceControlBlock.fOutxDsrFlow = FALSE;
409 deviceControlBlock.fOutX = TRUE;
410 break;
411 case RtsCts :
412 deviceControlBlock.fOutxCtsFlow = TRUE;
413 deviceControlBlock.fOutxDsrFlow = FALSE;
414 deviceControlBlock.fOutX = FALSE;
415 break;
418 if (!IsOpen()) {
419 osError = EBADF;
420 lastError = NotOpen;
421 lastError = BadParameter;
422 return FALSE;
425 if (SetCommState(&deviceControlBlock) < 0) {
426 osError = EINVAL;
427 return FALSE;
430 PAssert(GetCommState(os_handle, &deviceControlBlock) == 0,
431 POperatingSystemError);
432 return TRUE;
436 BOOL PSerialChannel::Open(const PString & port, DWORD speed, BYTE data,
437 Parity parity, BYTE stop, FlowControl inputFlow, FlowControl outputFlow)
439 Close();
441 os_handle = OpenComm(port, InputQueueSize, OutputQueueSize);
442 if (os_handle < 0) {
443 switch (os_handle) {
444 case IE_BADID :
445 case IE_HARDWARE :
446 osError = ENOENT;
447 lastError = NotFound;
448 break;
449 case IE_OPEN :
450 osError = EBUSY;
451 lastError = DeviceInUse;
452 break;
453 case IE_MEMORY :
454 osError = ENOMEM;
455 lastError = NoMemory;
456 break;
457 case IE_BAUDRATE :
458 case IE_BYTESIZE :
459 osError = EINVAL;
460 lastError = BadParameter;
461 break;
462 default :
463 osError = EFAULT;
464 lastError = Miscellaneous;
466 os_handle = -1;
467 return FALSE;
470 deviceControlBlock.Id = (BYTE)os_handle;
471 SetCommState(&deviceControlBlock);
473 if (!SetCommsParam(speed, data, parity, stop, inputFlow, outputFlow)) {
474 CloseComm(os_handle);
475 return FALSE;
478 SetCommEventMask(os_handle, EV_CTSS|EV_DSR|EV_RING|EV_RLSDS);
479 return TRUE;
483 BOOL PSerialChannel::SetSpeed(DWORD speed)
485 return SetCommsParam(speed,
486 0, DefaultParity, 0, DefaultFlowControl, DefaultFlowControl);
490 DWORD PSerialChannel::GetSpeed() const
492 switch (deviceControlBlock.BaudRate) {
493 case CBR_110 :
494 return 110;
495 case CBR_300 :
496 return 300;
497 case CBR_600 :
498 return 600;
499 case CBR_1200 :
500 return 1200;
501 case CBR_2400 :
502 return 2400;
503 case CBR_4800 :
504 return 4800;
505 case CBR_9600 :
506 return 9600;
507 case CBR_14400 :
508 return 14400;
509 case CBR_19200 :
510 return 19200;
511 case CBR_38400 :
512 return 38400;
513 case CBR_56000 :
514 return 56000;
515 case CBR_128000 :
516 return 128000;
517 case CBR_256000 :
518 return 256000;
520 return deviceControlBlock.BaudRate;
524 BOOL PSerialChannel::SetDataBits(BYTE data)
526 return SetCommsParam(0,
527 data, DefaultParity, 0, DefaultFlowControl, DefaultFlowControl);
531 BYTE PSerialChannel::GetDataBits() const
533 return deviceControlBlock.ByteSize;
537 BOOL PSerialChannel::SetParity(Parity parity)
539 return SetCommsParam(0,0, parity, 0, DefaultFlowControl, DefaultFlowControl);
543 PSerialChannel::Parity PSerialChannel::GetParity() const
545 switch (deviceControlBlock.Parity) {
546 case ODDPARITY :
547 return OddParity;
548 case EVENPARITY :
549 return EvenParity;
550 case MARKPARITY :
551 return MarkParity;
552 case SPACEPARITY :
553 return SpaceParity;
555 return NoParity;
559 BOOL PSerialChannel::SetStopBits(BYTE stop)
561 return SetCommsParam(0,
562 0, DefaultParity, stop, DefaultFlowControl, DefaultFlowControl);
566 BYTE PSerialChannel::GetStopBits() const
568 return (BYTE)(deviceControlBlock.StopBits == ONESTOPBIT ? 1 : 2);
572 BOOL PSerialChannel::SetInputFlowControl(FlowControl flowControl)
574 return SetCommsParam(0,0, DefaultParity, 0, flowControl, DefaultFlowControl);
578 PSerialChannel::FlowControl PSerialChannel::GetInputFlowControl() const
580 if (deviceControlBlock.fRtsflow)
581 return RtsCts;
582 if (deviceControlBlock.fInX != 0)
583 return XonXoff;
584 return NoFlowControl;
588 BOOL PSerialChannel::SetOutputFlowControl(FlowControl flowControl)
590 return SetCommsParam(0,0, DefaultParity, 0, DefaultFlowControl, flowControl);
594 PSerialChannel::FlowControl PSerialChannel::GetOutputFlowControl() const
596 if (deviceControlBlock.fOutxCtsFlow != 0)
597 return RtsCts;
598 if (deviceControlBlock.fOutX != 0)
599 return XonXoff;
600 return NoFlowControl;
604 void PSerialChannel::SetDTR(BOOL state)
606 if (!IsOpen()) {
607 osError = EBADF;
608 lastError = NotOpen;
609 return;
612 PAssert(EscapeCommFunction(os_handle, state ? SETDTR : CLRDTR) == 0,
613 POperatingSystemError);
617 void PSerialChannel::SetRTS(BOOL state)
619 if (!IsOpen()) {
620 osError = EBADF;
621 lastError = NotOpen;
622 return;
625 PAssert(EscapeCommFunction(os_handle, state ? SETRTS : CLRRTS) == 0,
626 POperatingSystemError);
630 void PSerialChannel::SetBreak(BOOL state)
632 if (!IsOpen()) {
633 osError = EBADF;
634 lastError = NotOpen;
635 return;
638 if (state)
639 PAssert(SetCommBreak(os_handle), POperatingSystemError);
640 else
641 PAssert(ClearCommBreak(os_handle), POperatingSystemError);
645 BOOL PSerialChannel::GetCTS()
647 if (!IsOpen()) {
648 osError = EBADF;
649 lastError = NotOpen;
650 return FALSE;
653 return (GetCommEventMask(os_handle, 0)&EV_CTSS) != 0;
657 BOOL PSerialChannel::GetDSR()
659 if (!IsOpen()) {
660 osError = EBADF;
661 lastError = NotOpen;
662 return FALSE;
665 return (GetCommEventMask(os_handle, 0)&EV_DSR) != 0;
669 BOOL PSerialChannel::GetDCD()
671 if (!IsOpen()) {
672 osError = EBADF;
673 lastError = NotOpen;
674 return FALSE;
677 return (GetCommEventMask(os_handle, 0)&EV_RLSDS) != 0;
681 BOOL PSerialChannel::GetRing()
683 if (!IsOpen()) {
684 osError = EBADF;
685 lastError = NotOpen;
686 return FALSE;
689 return (GetCommEventMask(os_handle, 0)&EV_RING) != 0;
693 PStringList PSerialChannel::GetPortNames()
695 static char buf[] = "COM ";
696 PStringList ports;
697 for (char p = '1'; p <= '4'; p++) {
698 buf[3] = p;
699 ports.Append(new PString(buf));
701 return ports;
705 ///////////////////////////////////////////////////////////////////////////////
706 // PPipeChannel
708 BOOL PPipeChannel::Execute()
710 if (hasRun)
711 return FALSE;
713 flush();
714 if (os_handle >= 0) {
715 _close(os_handle);
716 os_handle = -1;
719 static struct {
720 DWORD pifFlags;
721 DWORD displayFlags;
722 struct {
723 DWORD offset;
724 WORD selector;
725 } exePath, programArguments, workingDirectory;
726 WORD desiredV86Pages;
727 WORD minimumV86Pages;
728 WORD foregroundPriority;
729 WORD backgroundPriority;
730 WORD maximumEMS;
731 WORD minimumEMS;
732 WORD maximumXMS;
733 WORD minimumXMS;
734 DWORD unknown;
735 char windowTitle[128];
736 } seb = {
737 0x40000006, // Runs in background, runs in window, close on exit
738 0x0000001f, // Emulate text mode, no monitor ports
739 { 0, 0 },
740 { 0, 0 },
741 { 0, 0 },
742 0xffff, // desired memory
743 0xffff, // minimum memory
744 100, // foreground priority
745 50, // background priority
746 0x0400, // maximum EMS
747 0, // minimum EMS
748 0x4000, // maximum XMS
749 0, // minimum XMS
750 0, // unknown
751 "PWLib Pipe Channel Process"
754 char * commandDotCom = getenv("COMSPEC");
755 if (commandDotCom == NULL)
756 commandDotCom = "C:\\COMMAND.COM";
757 seb.exePath.selector = SELECTOROF(commandDotCom);
758 seb.exePath.offset = OFFSETOF (commandDotCom);
760 PString commandArguments = " /c " + subProgName;
761 const char * argumentPointer = commandArguments;
762 seb.programArguments.selector = SELECTOROF(argumentPointer);
763 seb.programArguments.offset = OFFSETOF (argumentPointer);
765 static char * currentDirectory = ".";
766 seb.workingDirectory.selector = SELECTOROF(currentDirectory);
767 seb.workingDirectory.offset = OFFSETOF (currentDirectory);
769 void (FAR * shellEntry)();
770 _asm mov ax,1684h; //Get Shell VXDs protected mode entry point
771 _asm mov bx,0017h;
772 _asm int 2fh;
773 _asm mov word ptr [shellEntry], di;
774 _asm mov word ptr [shellEntry+2], es;
775 if (shellEntry == NULL)
776 return FALSE;
778 _asm lea di, word ptr seb;
779 _asm mov dx, 3;
780 _asm push es;
781 _asm push ss;
782 _asm pop es;
783 shellEntry();
784 _asm pop es;
786 DWORD hVirtualMachine;
787 #if defined(_MSC_VER)
788 _asm _emit 66h;
789 #else
790 _asm db 66h;
791 #endif
792 _asm mov word ptr hVirtualMachine, ax; // Really EAX
793 if (hVirtualMachine == 0)
794 return FALSE;
796 if (fromChild.IsEmpty())
797 return TRUE;
799 // Wait for child to complete
802 os_handle = _open(fromChild, _O_RDONLY);
803 return ConvertOSError(os_handle);
807 ///////////////////////////////////////////////////////////////////////////////
808 // Configuration files
810 void PConfig::Construct(Source src)
812 switch (src) {
813 case System :
814 location = "WIN.INI";
815 break;
817 case Application :
818 PFilePath appFile = PProcess::Current()->GetFile();
819 location = appFile.GetDirectory() + appFile.GetTitle() + ".INI";
820 break;
823 source = src;
827 void PConfig::Construct(const PFilePath & filename)
829 location = filename;
830 source = NumSources;
834 PStringList PConfig::GetSections()
836 PStringList sections;
838 if (source != Environment) {
839 PString buf;
840 char * ptr = buf.GetPointer(10000);
841 GetPrivateProfileString(NULL, NULL, "", ptr, 9999, location);
842 while (*ptr != '\0') {
843 sections.AppendString(ptr);
844 ptr += strlen(ptr)+1;
848 return sections;
852 PStringList PConfig::GetKeys(const PString & section) const
854 PStringList keys;
856 if (source == Environment) {
857 char ** ptr = _environ;
858 while (*ptr != NULL) {
859 PString buf = *ptr++;
860 keys.AppendString(buf.Left(buf.Find('=')));
863 else {
864 PString buf;
865 char * ptr = buf.GetPointer(10000);
866 GetPrivateProfileString(section, NULL, "", ptr, 9999, location);
867 while (*ptr != '\0') {
868 keys.AppendString(ptr);
869 ptr += strlen(ptr)+1;
873 return keys;
877 void PConfig::DeleteSection(const PString & section)
879 if (source == Environment)
880 return;
882 PAssert(!section.IsEmpty(), PInvalidParameter);
883 PAssertOS(WritePrivateProfileString(section, NULL, NULL, location));
887 void PConfig::DeleteKey(const PString & section, const PString & key)
889 PAssert(!key.IsEmpty(), PInvalidParameter);
891 if (source == Environment) {
892 PString str = key;
893 PAssert(str.Find('=') == P_MAX_INDEX, PInvalidParameter);
894 _putenv(str + "=");
896 else {
897 PAssert(!section.IsEmpty(), PInvalidParameter);
898 PAssertOS(WritePrivateProfileString(section, key, NULL, location));
903 PString PConfig::GetString(const PString & section,
904 const PString & key, const PString & dflt)
906 PString str;
908 PAssert(!key.IsEmpty(), PInvalidParameter);
910 if (source == Environment) {
911 PAssert(key.Find('=') == P_MAX_INDEX, PInvalidParameter);
912 char * env = getenv(key);
913 if (env != NULL)
914 str = env;
915 else
916 str = dflt;
918 else {
919 PAssert(!section.IsEmpty(), PInvalidParameter);
920 GetPrivateProfileString(section, key, dflt,
921 str.GetPointer(1000), 999, location);
922 str.MakeMinimumSize();
925 return str;
929 void PConfig::SetString(const PString & section,
930 const PString & key, const PString & value)
932 PAssert(!key.IsEmpty(), PInvalidParameter);
934 if (source == Environment) {
935 PString str = key;
936 PAssert(str.Find('=') == P_MAX_INDEX, PInvalidParameter);
937 _putenv(str + "=" + value);
939 else {
940 PAssert(!section.IsEmpty(), PInvalidParameter);
941 PAssertOS(WritePrivateProfileString(section, key, value, location));
947 ///////////////////////////////////////////////////////////////////////////////
948 // Threads
950 static char NEAR * NEAR * const StackBase = (char NEAR * NEAR *)0xa;
951 static char NEAR * NEAR * const StackUsed = (char NEAR * NEAR *)0xc;
952 static char NEAR * NEAR * const StackTop = (char NEAR * NEAR *)0xe;
954 void PThread::SwitchContext(PThread * from)
956 if (from == this) // Switching to itself, ie is only thread
957 return;
959 if (setjmp(from->context) != 0) // Are being reactivated from previous yield
960 return;
962 // Save some magic global variables in MS-Windows DGROUP segment
963 from->stackBase = *StackBase;
964 from->stackTop = *StackTop;
965 from->stackUsed = *StackTop - *StackUsed;
967 if (status == Starting) {
968 if (setjmp(context) != 0)
969 BeginThread();
970 context[3] = (int)stackTop-16; // Change the stack pointer in jmp_buf
973 // Restore those MS-Windows magic global for the next context
974 *StackBase = stackBase;
975 *StackTop = stackTop;
976 *StackUsed = stackTop - stackUsed;
978 longjmp(context, TRUE);
979 PAssertAlways("longjmp failed"); // Should never get here
983 ///////////////////////////////////////////////////////////////////////////////
984 // PDynaLink
986 PDynaLink::PDynaLink()
988 _hDLL = NULL;
992 PDynaLink::PDynaLink(const PString & name)
994 Open(name);
998 PDynaLink::~PDynaLink()
1000 Close();
1004 BOOL PDynaLink::Open(const PString & name)
1006 if ((_hDLL = LoadLibrary(name)) < HINSTANCE_ERROR)
1007 _hDLL = NULL;
1008 return _hDLL != NULL;
1012 void PDynaLink::Close()
1014 if (_hDLL != NULL) {
1015 FreeLibrary(_hDLL);
1016 _hDLL = NULL;
1021 BOOL PDynaLink::IsLoaded() const
1023 return _hDLL != NULL;
1027 BOOL PDynaLink::GetFunction(PINDEX index, Function & func)
1029 if (_hDLL == NULL)
1030 return FALSE;
1032 FARPROC p = GetProcAddress(_hDLL, (LPSTR)(DWORD)LOWORD(index));
1033 if (p == NULL)
1034 return FALSE;
1036 func = (Function)p;
1037 return TRUE;
1041 BOOL PDynaLink::GetFunction(const PString & name, Function & func)
1043 if (_hDLL == NULL)
1044 return FALSE;
1046 FARPROC p = GetProcAddress(_hDLL, name);
1047 if (p == NULL)
1048 return FALSE;
1050 func = (Function)p;
1051 return TRUE;
1056 // End Of File ///////////////////////////////////////////////////////////////