mswin.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:24k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * mswin.cxx
  3.  *
  4.  * General class implementations for 16 bit Windows.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  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/
  14.  *
  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.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: mswin.cxx,v $
  30.  * Revision 1.17  1998/09/24 03:30:51  robertj
  31.  * Added open software license.
  32.  *
  33.  * Revision 1.16  1996/02/15 14:55:02  robertj
  34.  * Win16 compatibility
  35.  *
  36.  * Revision 1.15  1996/01/28 02:55:33  robertj
  37.  * WIN16 support.
  38.  *
  39.  * Revision 1.14  1995/12/10 11:58:37  robertj
  40.  * Added WIN32 registry support for PConfig objects.
  41.  *
  42.  * Revision 1.13  1995/08/24 12:40:52  robertj
  43.  * Changed PChannel so not a PContainer.
  44.  *
  45.  * Revision 1.12  1995/07/02 01:24:45  robertj
  46.  * Added running of hidden VM for DOS program in PPipeChannel.
  47.  *
  48.  * Revision 1.11  1995/06/17 00:59:23  robertj
  49.  * Moved PPipeChannel::Execute from common dos/windows to individual files.
  50.  *
  51.  * Revision 1.10  1995/03/12 05:00:06  robertj
  52.  * Re-organisation of DOS/WIN16 and WIN32 platforms to maximise common code.
  53.  * Used built-in equate for WIN32 API (_WIN32).
  54.  *
  55.  * Revision 1.9  1995/01/09  12:28:00  robertj
  56.  * Added implementation for PConfig::Environment
  57.  *
  58.  * Revision 1.8  1994/10/23  05:41:29  robertj
  59.  * Fixed config file bugs.
  60.  *
  61.  * Revision 1.7  1994/08/22  00:18:02  robertj
  62.  * Fixed bug in serial comms timers.
  63.  *
  64.  * Revision 1.6  1994/08/04  13:24:27  robertj
  65.  * Added DCB so can set paraemters on closed channel.
  66.  *
  67.  * Revision 1.5  1994/07/27  06:00:10  robertj
  68.  * Backup
  69.  *
  70.  * Revision 1.4  1994/07/21  12:35:18  robertj
  71.  * *** empty log message ***
  72.  *
  73.  * Revision 1.3  1994/07/17  11:01:04  robertj
  74.  * Ehancements, implementation, bug fixes etc.
  75.  *
  76.  * Revision 1.2  1994/07/02  03:18:09  robertj
  77.  * Multi-threading implementation.
  78.  *
  79.  * Revision 1.1  1994/06/25  12:13:01  robertj
  80.  * Initial revision
  81.  *
  82. // Revision 1.1  1994/04/01  14:39:35  robertj
  83. // Initial revision
  84. //
  85.  */
  86. #include "ptlib.h"
  87. #include <errno.h>
  88. #include <fcntl.h>
  89. #include <stdresid.h>
  90. extern "C" HINSTANCE _hInstance;
  91. ///////////////////////////////////////////////////////////////////////////////
  92. // PTime
  93. PString PTime::GetTimeSeparator()
  94. {
  95.   PString str;
  96.   GetProfileString("intl", "sTime", ":", str.GetPointer(100), 99);
  97.   str.MakeMinimumSize();
  98.   return str;
  99. }
  100. BOOL PTime::GetTimeAMPM()
  101. {
  102.   return GetProfileInt("intl", "iTime", 0) != 0;
  103. }
  104. PString PTime::GetTimeAM()
  105. {
  106.   PString str;
  107.   GetProfileString("intl", "s1159", "am", str.GetPointer(100), 99);
  108.   str.MakeMinimumSize();
  109.   return str;
  110. }
  111. PString PTime::GetTimePM()
  112. {
  113.   PString str;
  114.   GetProfileString("intl", "s2359", "pm", str.GetPointer(100), 99);
  115.   str.MakeMinimumSize();
  116.   return str;
  117. }
  118. PString PTime::GetDayName(Weekdays dayOfWeek, NameType type)
  119. {
  120.   static const char * const weekdays[] = {
  121.     "Sunday", "Monday", "Tuesday", "Wednesday",
  122.     "Thursday", "Friday", "Saturday"
  123.   };
  124.   static const char * const abbrev_weekdays[] = {
  125.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  126.   };
  127.   PString str;
  128.   if (LoadString(_hInstance, dayOfWeek+
  129.         (type != FullName ? PSTD_ID_STR_ABBREV_WEEKDAYS : PSTD_ID_STR_WEEKDAYS),
  130.         str.GetPointer(100), 99) == 0)
  131.     return (type != FullName ? abbrev_weekdays : weekdays)[dayOfWeek];
  132.   str.MakeMinimumSize();
  133.   return str;
  134. }
  135. PString PTime::GetDateSeparator()
  136. {
  137.   PString str;
  138.   GetProfileString("intl", "sDate", "-", str.GetPointer(100), 99);
  139.   str.MakeMinimumSize();
  140.   return str;
  141. }
  142. PString PTime::GetMonthName(Months month, NameType type)
  143. {
  144.   static const char * const months[] = { "",
  145.     "January", "February", "March", "April", "May", "June",
  146.     "July", "August", "September", "October", "November", "December"
  147.   };
  148.   static const char * const abbrev_months[] = {
  149.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  150.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  151.   };
  152.   PString str;
  153.   if (LoadString(_hInstance, month+
  154.        (UINT)(type != FullName ? PSTD_ID_STR_ABBREV_MONTHS : PSTD_ID_STR_MONTHS),
  155.        str.GetPointer(100), 99) == 0)
  156.     return (type != FullName ? abbrev_months : months)[month];
  157.   str.MakeMinimumSize();
  158.   return str;
  159. }
  160. PTime::DateOrder PTime::GetDateOrder()
  161. {
  162.   return (DateOrder)GetProfileInt("intl", "iDate", 0);
  163. }
  164. BOOL PTime::IsDaylightSavings()
  165. {
  166.   return FALSE;
  167. }
  168. int PTime::GetTimeZone(TimeZoneType type)
  169. {
  170.   return 0;
  171. }
  172. PString PTime::GetTimeZoneString(TimeZoneType type)
  173. {
  174.   return "";
  175. }
  176. ///////////////////////////////////////////////////////////////////////////////
  177. // PSerialChannel
  178. void PSerialChannel::Construct()
  179. {
  180.   char str[50];
  181.   strcpy(str, "com1");
  182.   GetProfileString("ports", str, "9600,n,8,1,x", &str[5], sizeof(str)-6);
  183.   str[4] = ':';
  184.   if (!BuildCommDCB(str, &deviceControlBlock)) {
  185.     osError = EINVAL;
  186.     lastError = BadParameter;
  187.   }
  188. }
  189. PString PSerialChannel::GetName() const
  190. {
  191.   if (IsOpen())
  192.     return psprintf("COM%i", os_handle+1);
  193.   return PString();
  194. }
  195. BOOL PSerialChannel::IsReadBlocked(PObject * obj)
  196. {
  197.   PSerialChannel & chan = *(PSerialChannel *)PAssertNULL(obj);
  198.   COMSTAT stat;
  199.   GetCommError(chan.os_handle, &stat);
  200.   return stat.cbInQue <= 0 &&
  201.          (chan.readTimeout == PMaxTimeInterval || chan.readTimer.IsRunning());
  202. }
  203. BOOL PSerialChannel::Read(void * buf, PINDEX len)
  204. {
  205.   lastReadCount = 0;
  206.   if (!IsOpen()) {
  207.     PThread::Yield();
  208.     osError = EBADF;
  209.     lastError = NotOpen;
  210.     return FALSE;
  211.   }
  212.   if (readTimeout != PMaxTimeInterval)
  213.     readTimer = readTimeout;
  214.   if (IsReadBlocked(this))
  215.     PThread::Current()->Block(&PSerialChannel::IsReadBlocked, this);
  216.   lastReadCount = ReadComm(os_handle, buf, len);
  217.   if (lastReadCount > 0)
  218.     return TRUE;
  219.   COMSTAT stat;
  220.   GetCommError(os_handle, &stat);
  221.   osError = EFAULT;
  222.   lastReadCount = -lastReadCount;
  223.   return lastReadCount > 0;
  224. }
  225. BOOL PSerialChannel::IsWriteBlocked(PObject * obj)
  226. {
  227.   PSerialChannel & chan = *(PSerialChannel *)PAssertNULL(obj);
  228.   COMSTAT stat;
  229.   GetCommError(chan.os_handle, &stat);
  230.   return stat.cbOutQue >= OutputQueueSize &&
  231.        (chan.writeTimeout == PMaxTimeInterval || chan.writeTimer.IsRunning());
  232. }
  233. BOOL PSerialChannel::Write(const void * buf, PINDEX len)
  234. {
  235.   lastWriteCount = 0;
  236.   if (!IsOpen()) {
  237.     osError = EBADF;
  238.     lastError = NotOpen;
  239.     return FALSE;
  240.   }
  241.   if (writeTimeout != PMaxTimeInterval)
  242.     writeTimer = writeTimeout;
  243.   if (IsWriteBlocked(this))
  244.     PThread::Current()->Block(&PSerialChannel::IsWriteBlocked, this);
  245.   lastWriteCount = WriteComm(os_handle, buf, len);
  246.   if (lastWriteCount <= 0) {
  247.     COMSTAT stat;
  248.     GetCommError(os_handle, &stat);
  249.     osError = EFAULT;
  250.     lastWriteCount = -lastWriteCount;
  251.   }
  252.   return lastWriteCount >= len;
  253. }
  254. BOOL PSerialChannel::Close()
  255. {
  256.   if (!IsOpen()) {
  257.     osError = EBADF;
  258.     lastError = NotOpen;
  259.     return FALSE;
  260.   }
  261.   BOOL retVal = CloseComm(os_handle) == 0;
  262.   os_handle = -1;
  263.   return retVal;
  264. }
  265. BOOL PSerialChannel::SetCommsParam(DWORD speed, BYTE data, Parity parity,
  266.                      BYTE stop, FlowControl inputFlow, FlowControl outputFlow)
  267. {
  268.   if (IsOpen())
  269.     PAssert(GetCommState(os_handle, &deviceControlBlock) == 0,
  270.                                                         POperatingSystemError);
  271.   switch (speed) {
  272.     case 0 :
  273.       break;
  274.     case 14400 :
  275.       deviceControlBlock.BaudRate = CBR_14400;
  276.       break;
  277.     case 19200 :
  278.       deviceControlBlock.BaudRate = CBR_19200;
  279.       break;
  280.     case 38400 :
  281.       deviceControlBlock.BaudRate = CBR_38400;
  282.       break;
  283.     case 56000 :
  284.       deviceControlBlock.BaudRate = CBR_56000;
  285.       break;
  286.     case 128000 :
  287.       deviceControlBlock.BaudRate = CBR_128000;
  288.       break;
  289.     case 256000 :
  290.       deviceControlBlock.BaudRate = CBR_256000;
  291.       break;
  292.     default :
  293.       if (speed > 9600) {
  294.         osError = EINVAL;
  295.         return FALSE;
  296.       }
  297.       deviceControlBlock.BaudRate = (UINT)speed;
  298.   }
  299.   if (data > 0)
  300.     deviceControlBlock.ByteSize = data;
  301.   switch (parity) {
  302.     case NoParity :
  303.       deviceControlBlock.Parity = NOPARITY;
  304.       break;
  305.     case OddParity :
  306.       deviceControlBlock.Parity = ODDPARITY;
  307.       break;
  308.     case EvenParity :
  309.       deviceControlBlock.Parity = EVENPARITY;
  310.       break;
  311.     case MarkParity :
  312.       deviceControlBlock.Parity = MARKPARITY;
  313.       break;
  314.     case SpaceParity :
  315.       deviceControlBlock.Parity = SPACEPARITY;
  316.       break;
  317.   }
  318.   switch (stop) {
  319.     case 1 :
  320.       deviceControlBlock.StopBits = ONESTOPBIT;
  321.       break;
  322.     case 2 :
  323.       deviceControlBlock.StopBits = TWOSTOPBITS;
  324.       break;
  325.   }
  326.   switch (inputFlow) {
  327.     case NoFlowControl :
  328.       deviceControlBlock.fRtsflow = FALSE;
  329.       deviceControlBlock.fInX = FALSE;
  330.       break;
  331.     case XonXoff :
  332.       deviceControlBlock.fRtsflow = FALSE;
  333.       deviceControlBlock.fInX = TRUE;
  334.       break;
  335.     case RtsCts :
  336.       deviceControlBlock.fRtsflow = TRUE;
  337.       deviceControlBlock.fInX = FALSE;
  338.       break;
  339.   }
  340.   switch (outputFlow) {
  341.     case NoFlowControl :
  342.       deviceControlBlock.fOutxCtsFlow = FALSE;
  343.       deviceControlBlock.fOutxDsrFlow = FALSE;
  344.       deviceControlBlock.fOutX = FALSE;
  345.       break;
  346.     case XonXoff :
  347.       deviceControlBlock.fOutxCtsFlow = FALSE;
  348.       deviceControlBlock.fOutxDsrFlow = FALSE;
  349.       deviceControlBlock.fOutX = TRUE;
  350.       break;
  351.     case RtsCts :
  352.       deviceControlBlock.fOutxCtsFlow = TRUE;
  353.       deviceControlBlock.fOutxDsrFlow = FALSE;
  354.       deviceControlBlock.fOutX = FALSE;
  355.       break;
  356.   }
  357.   if (!IsOpen()) {
  358.     osError = EBADF;
  359.     lastError = NotOpen;
  360.     lastError = BadParameter;
  361.     return FALSE;
  362.   }
  363.   if (SetCommState(&deviceControlBlock) < 0) {
  364.     osError = EINVAL;
  365.     return FALSE;
  366.   }
  367.   PAssert(GetCommState(os_handle, &deviceControlBlock) == 0,
  368.                                                         POperatingSystemError);
  369.   return TRUE;
  370. }
  371. BOOL PSerialChannel::Open(const PString & port, DWORD speed, BYTE data,
  372.        Parity parity, BYTE stop, FlowControl inputFlow, FlowControl outputFlow)
  373. {
  374.   Close();
  375.   os_handle = OpenComm(port, InputQueueSize, OutputQueueSize);
  376.   if (os_handle < 0) {
  377.     switch (os_handle) {
  378.       case IE_BADID :
  379.       case IE_HARDWARE :
  380.         osError = ENOENT;
  381.         lastError = NotFound;
  382.         break;
  383.       case IE_OPEN :
  384.         osError = EBUSY;
  385.         lastError = DeviceInUse;
  386.         break;
  387.       case IE_MEMORY :
  388.         osError = ENOMEM;
  389.         lastError = NoMemory;
  390.         break;
  391.       case IE_BAUDRATE :
  392.       case IE_BYTESIZE :
  393.         osError = EINVAL;
  394.         lastError = BadParameter;
  395.         break;
  396.       default :
  397.         osError = EFAULT;
  398.         lastError = Miscellaneous;
  399.     }
  400.     os_handle = -1;
  401.     return FALSE;
  402.   }
  403.   deviceControlBlock.Id = (BYTE)os_handle;
  404.   SetCommState(&deviceControlBlock);
  405.   if (!SetCommsParam(speed, data, parity, stop, inputFlow, outputFlow)) {
  406.     CloseComm(os_handle);
  407.     return FALSE;
  408.   }
  409.   SetCommEventMask(os_handle, EV_CTSS|EV_DSR|EV_RING|EV_RLSDS);
  410.   return TRUE;
  411. }
  412. BOOL PSerialChannel::SetSpeed(DWORD speed)
  413. {
  414.   return SetCommsParam(speed,
  415.                  0, DefaultParity, 0, DefaultFlowControl, DefaultFlowControl);
  416. }
  417. DWORD PSerialChannel::GetSpeed() const
  418. {
  419.   switch (deviceControlBlock.BaudRate) {
  420.     case CBR_110 :
  421.       return 110;
  422.     case CBR_300 :
  423.       return 300;
  424.     case CBR_600 :
  425.       return 600;
  426.     case CBR_1200 :
  427.       return 1200;
  428.     case CBR_2400 :
  429.       return 2400;
  430.     case CBR_4800 :
  431.       return 4800;
  432.     case CBR_9600 :
  433.       return 9600;
  434.     case CBR_14400 :
  435.       return 14400;
  436.     case CBR_19200 :
  437.       return 19200;
  438.     case CBR_38400 :
  439.       return 38400;
  440.     case CBR_56000 :
  441.       return 56000;
  442.     case CBR_128000 :
  443.       return 128000;
  444.     case CBR_256000 :
  445.       return 256000;
  446.   }
  447.   return deviceControlBlock.BaudRate;
  448. }
  449. BOOL PSerialChannel::SetDataBits(BYTE data)
  450. {
  451.   return SetCommsParam(0,
  452.               data, DefaultParity, 0, DefaultFlowControl, DefaultFlowControl);
  453. }
  454. BYTE PSerialChannel::GetDataBits() const
  455. {
  456.   return deviceControlBlock.ByteSize;
  457. }
  458. BOOL PSerialChannel::SetParity(Parity parity)
  459. {
  460.   return SetCommsParam(0,0, parity, 0, DefaultFlowControl, DefaultFlowControl);
  461. }
  462. PSerialChannel::Parity PSerialChannel::GetParity() const
  463. {
  464.   switch (deviceControlBlock.Parity) {
  465.     case ODDPARITY :
  466.       return OddParity;
  467.     case EVENPARITY :
  468.       return EvenParity;
  469.     case MARKPARITY :
  470.       return MarkParity;
  471.     case SPACEPARITY :
  472.       return SpaceParity;
  473.   }
  474.   return NoParity;
  475. }
  476. BOOL PSerialChannel::SetStopBits(BYTE stop)
  477. {
  478.   return SetCommsParam(0,
  479.                0, DefaultParity, stop, DefaultFlowControl, DefaultFlowControl);
  480. }
  481. BYTE PSerialChannel::GetStopBits() const
  482. {
  483.   return (BYTE)(deviceControlBlock.StopBits == ONESTOPBIT ? 1 : 2);
  484. }
  485. BOOL PSerialChannel::SetInputFlowControl(FlowControl flowControl)
  486. {
  487.   return SetCommsParam(0,0, DefaultParity, 0, flowControl, DefaultFlowControl);
  488. }
  489. PSerialChannel::FlowControl PSerialChannel::GetInputFlowControl() const
  490. {
  491.   if (deviceControlBlock.fRtsflow)
  492.     return RtsCts;
  493.   if (deviceControlBlock.fInX != 0)
  494.     return XonXoff;
  495.   return NoFlowControl;
  496. }
  497. BOOL PSerialChannel::SetOutputFlowControl(FlowControl flowControl)
  498. {
  499.   return SetCommsParam(0,0, DefaultParity, 0, DefaultFlowControl, flowControl);
  500. }
  501. PSerialChannel::FlowControl PSerialChannel::GetOutputFlowControl() const
  502. {
  503.   if (deviceControlBlock.fOutxCtsFlow != 0)
  504.     return RtsCts;
  505.   if (deviceControlBlock.fOutX != 0)
  506.     return XonXoff;
  507.   return NoFlowControl;
  508. }
  509. void PSerialChannel::SetDTR(BOOL state)
  510. {
  511.   if (!IsOpen()) {
  512.     osError = EBADF;
  513.     lastError = NotOpen;
  514.     return;
  515.   }
  516.   PAssert(EscapeCommFunction(os_handle, state ? SETDTR : CLRDTR) == 0,
  517.                                                       POperatingSystemError);
  518. }
  519. void PSerialChannel::SetRTS(BOOL state)
  520. {
  521.   if (!IsOpen()) {
  522.     osError = EBADF;
  523.     lastError = NotOpen;
  524.     return;
  525.   }
  526.   PAssert(EscapeCommFunction(os_handle, state ? SETRTS : CLRRTS) == 0,
  527.                                                       POperatingSystemError);
  528. }
  529. void PSerialChannel::SetBreak(BOOL state)
  530. {
  531.   if (!IsOpen()) {
  532.     osError = EBADF;
  533.     lastError = NotOpen;
  534.     return;
  535.   }
  536.   if (state)
  537.     PAssert(SetCommBreak(os_handle), POperatingSystemError);
  538.   else
  539.     PAssert(ClearCommBreak(os_handle), POperatingSystemError);
  540. }
  541. BOOL PSerialChannel::GetCTS()
  542. {
  543.   if (!IsOpen()) {
  544.     osError = EBADF;
  545.     lastError = NotOpen;
  546.     return FALSE;
  547.   }
  548.   return (GetCommEventMask(os_handle, 0)&EV_CTSS) != 0;
  549. }
  550. BOOL PSerialChannel::GetDSR()
  551. {
  552.   if (!IsOpen()) {
  553.     osError = EBADF;
  554.     lastError = NotOpen;
  555.     return FALSE;
  556.   }
  557.   return (GetCommEventMask(os_handle, 0)&EV_DSR) != 0;
  558. }
  559. BOOL PSerialChannel::GetDCD()
  560. {
  561.   if (!IsOpen()) {
  562.     osError = EBADF;
  563.     lastError = NotOpen;
  564.     return FALSE;
  565.   }
  566.   return (GetCommEventMask(os_handle, 0)&EV_RLSDS) != 0;
  567. }
  568. BOOL PSerialChannel::GetRing()
  569. {
  570.   if (!IsOpen()) {
  571.     osError = EBADF;
  572.     lastError = NotOpen;
  573.     return FALSE;
  574.   }
  575.   return (GetCommEventMask(os_handle, 0)&EV_RING) != 0;
  576. }
  577. PStringList PSerialChannel::GetPortNames()
  578. {
  579.   static char buf[] = "COM ";
  580.   PStringList ports;
  581.   for (char p = '1'; p <= '4'; p++) {
  582.     buf[3] = p;
  583.     ports.Append(new PString(buf));
  584.   }
  585.   return ports;
  586. }
  587. ///////////////////////////////////////////////////////////////////////////////
  588. // PPipeChannel
  589. BOOL PPipeChannel::Execute()
  590. {
  591.   if (hasRun)
  592.     return FALSE;
  593.   flush();
  594.   if (os_handle >= 0) {
  595.     _close(os_handle);
  596.     os_handle = -1;
  597.   }
  598.   static struct {
  599.     DWORD pifFlags;
  600.     DWORD displayFlags;
  601.     struct {
  602.       DWORD offset;
  603.       WORD  selector;
  604.     } exePath, programArguments, workingDirectory;
  605.     WORD  desiredV86Pages;
  606.     WORD  minimumV86Pages;
  607.     WORD  foregroundPriority;
  608.     WORD  backgroundPriority;
  609.     WORD  maximumEMS;
  610.     WORD  minimumEMS;
  611.     WORD  maximumXMS;
  612.     WORD  minimumXMS;
  613.     DWORD unknown;
  614.     char  windowTitle[128];
  615.   } seb = {
  616.     0x40000006,  // Runs in background, runs in window, close on exit
  617.     0x0000001f,  // Emulate text mode, no monitor ports
  618.     { 0, 0 },
  619.     { 0, 0 },
  620.     { 0, 0 },
  621.     0xffff, // desired memory
  622.     0xffff, // minimum memory
  623.     100,    // foreground priority
  624.     50,     // background priority
  625.     0x0400, // maximum EMS
  626.     0,      // minimum EMS
  627.     0x4000, // maximum XMS
  628.     0,      // minimum XMS
  629.     0,      // unknown
  630.     "PWLib Pipe Channel Process"
  631.   };
  632.   char * commandDotCom = getenv("COMSPEC");
  633.   if (commandDotCom == NULL)
  634.     commandDotCom = "C:\COMMAND.COM";
  635.   seb.exePath.selector = SELECTOROF(commandDotCom);
  636.   seb.exePath.offset   = OFFSETOF  (commandDotCom);
  637.   PString commandArguments = " /c " + subProgName;
  638.   const char * argumentPointer = commandArguments;
  639.   seb.programArguments.selector = SELECTOROF(argumentPointer);
  640.   seb.programArguments.offset   = OFFSETOF  (argumentPointer);
  641.   
  642.   static char * currentDirectory = ".";
  643.   seb.workingDirectory.selector = SELECTOROF(currentDirectory);
  644.   seb.workingDirectory.offset   = OFFSETOF  (currentDirectory);
  645.   void (FAR * shellEntry)();
  646.   _asm mov  ax,1684h;  //Get Shell VXDs protected mode entry point
  647.   _asm mov  bx,0017h;
  648.   _asm int  2fh;
  649.   _asm mov  word ptr [shellEntry], di;
  650.   _asm mov  word ptr [shellEntry+2], es;
  651.   if (shellEntry == NULL)
  652.     return FALSE;
  653.   _asm lea  di, word ptr seb;
  654.   _asm mov  dx, 3;
  655.   _asm push es;
  656.   _asm push ss;
  657.   _asm pop  es;
  658.   shellEntry();
  659.   _asm pop  es;
  660.   DWORD hVirtualMachine;
  661. #if defined(_MSC_VER)
  662.   _asm _emit 66h;
  663. #else
  664.   _asm db 66h;
  665. #endif
  666.   _asm mov  word ptr hVirtualMachine, ax; // Really EAX
  667.   if (hVirtualMachine == 0)
  668.     return FALSE;
  669.   if (fromChild.IsEmpty())
  670.     return TRUE;
  671.   // Wait for child to complete
  672.   
  673.   os_handle = _open(fromChild, _O_RDONLY);
  674.   return ConvertOSError(os_handle);
  675. }
  676. ///////////////////////////////////////////////////////////////////////////////
  677. // Configuration files
  678. void PConfig::Construct(Source src)
  679. {
  680.   switch (src) {
  681.     case System :
  682.       location = "WIN.INI";
  683.       break;
  684.     case Application :
  685.       PFilePath appFile = PProcess::Current()->GetFile();
  686.       location = appFile.GetDirectory() + appFile.GetTitle() + ".INI";
  687.       break;
  688.   }
  689.   source = src;
  690. }
  691. void PConfig::Construct(const PFilePath & filename)
  692. {
  693.   location = filename;
  694.   source = NumSources;
  695. }
  696. PStringList PConfig::GetSections()
  697. {
  698.   PStringList sections;
  699.   if (source != Environment) {
  700.     PString buf;
  701.     char * ptr = buf.GetPointer(10000);
  702.     GetPrivateProfileString(NULL, NULL, "", ptr, 9999, location);
  703.     while (*ptr != '') {
  704.       sections.AppendString(ptr);
  705.       ptr += strlen(ptr)+1;
  706.     }
  707.   }
  708.   return sections;
  709. }
  710. PStringList PConfig::GetKeys(const PString & section) const
  711. {
  712.   PStringList keys;
  713.   if (source == Environment) {
  714.     char ** ptr = _environ;
  715.     while (*ptr != NULL) {
  716.       PString buf = *ptr++;
  717.       keys.AppendString(buf.Left(buf.Find('=')));
  718.     }
  719.   }
  720.   else {
  721.     PString buf;
  722.     char * ptr = buf.GetPointer(10000);
  723.     GetPrivateProfileString(section, NULL, "", ptr, 9999, location);
  724.     while (*ptr != '') {
  725.       keys.AppendString(ptr);
  726.       ptr += strlen(ptr)+1;
  727.     }
  728.   }
  729.   return keys;
  730. }
  731. void PConfig::DeleteSection(const PString & section)
  732. {
  733.   if (source == Environment)
  734.     return;
  735.   PAssert(!section.IsEmpty(), PInvalidParameter);
  736.   PAssertOS(WritePrivateProfileString(section, NULL, NULL, location));
  737. }
  738. void PConfig::DeleteKey(const PString & section, const PString & key)
  739. {
  740.   PAssert(!key.IsEmpty(), PInvalidParameter);
  741.   if (source == Environment) {
  742.     PString str = key;
  743.     PAssert(str.Find('=') == P_MAX_INDEX, PInvalidParameter);
  744.     _putenv(str + "=");
  745.   }
  746.   else {
  747.     PAssert(!section.IsEmpty(), PInvalidParameter);
  748.     PAssertOS(WritePrivateProfileString(section, key, NULL, location));
  749.   }
  750. }
  751. PString PConfig::GetString(const PString & section,
  752.                                     const PString & key, const PString & dflt)
  753. {
  754.   PString str;
  755.   PAssert(!key.IsEmpty(), PInvalidParameter);
  756.   if (source == Environment) {
  757.     PAssert(key.Find('=') == P_MAX_INDEX, PInvalidParameter);
  758.     char * env = getenv(key);
  759.     if (env != NULL)
  760.       str = env;
  761.     else
  762.       str = dflt;
  763.   }
  764.   else {
  765.     PAssert(!section.IsEmpty(), PInvalidParameter);
  766.     GetPrivateProfileString(section, key, dflt,
  767.                                         str.GetPointer(1000), 999, location);
  768.     str.MakeMinimumSize();
  769.   }
  770.   return str;
  771. }
  772. void PConfig::SetString(const PString & section,
  773.                                    const PString & key, const PString & value)
  774. {
  775.   PAssert(!key.IsEmpty(), PInvalidParameter);
  776.   if (source == Environment) {
  777.     PString str = key;
  778.     PAssert(str.Find('=') == P_MAX_INDEX, PInvalidParameter);
  779.     _putenv(str + "=" + value);
  780.   }
  781.   else {
  782.     PAssert(!section.IsEmpty(), PInvalidParameter);
  783.     PAssertOS(WritePrivateProfileString(section, key, value, location));
  784.   }
  785. }
  786. ///////////////////////////////////////////////////////////////////////////////
  787. // Threads
  788. static char NEAR * NEAR * const StackBase = (char NEAR * NEAR *)0xa;
  789. static char NEAR * NEAR * const StackUsed = (char NEAR * NEAR *)0xc;
  790. static char NEAR * NEAR * const StackTop  = (char NEAR * NEAR *)0xe;
  791. void PThread::SwitchContext(PThread * from)
  792. {
  793.   if (from == this) // Switching to itself, ie is only thread
  794.     return;
  795.   if (setjmp(from->context) != 0) // Are being reactivated from previous yield
  796.     return;
  797.   // Save some magic global variables in MS-Windows DGROUP segment
  798.   from->stackBase = *StackBase;
  799.   from->stackTop  = *StackTop;
  800.   from->stackUsed = *StackTop - *StackUsed;
  801.   if (status == Starting) {
  802.     if (setjmp(context) != 0)
  803.       BeginThread();
  804.     context[3] = (int)stackTop-16;  // Change the stack pointer in jmp_buf
  805.   }
  806.   // Restore those MS-Windows magic global for the next context
  807.   *StackBase = stackBase;
  808.   *StackTop = stackTop;
  809.   *StackUsed = stackTop - stackUsed;
  810.   
  811.   longjmp(context, TRUE);
  812.   PAssertAlways("longjmp failed"); // Should never get here
  813. }
  814. ///////////////////////////////////////////////////////////////////////////////
  815. // PDynaLink
  816. PDynaLink::PDynaLink()
  817. {
  818.   _hDLL = NULL;
  819. }
  820. PDynaLink::PDynaLink(const PString & name)
  821. {
  822.   Open(name);
  823. }
  824. PDynaLink::~PDynaLink()
  825. {
  826.   Close();
  827. }
  828. BOOL PDynaLink::Open(const PString & name)
  829. {
  830.   if ((_hDLL = LoadLibrary(name)) < HINSTANCE_ERROR)
  831.     _hDLL = NULL;
  832.   return _hDLL != NULL;
  833. }
  834. void PDynaLink::Close()
  835. {
  836.   if (_hDLL != NULL)
  837.     FreeLibrary(_hDLL);
  838. }
  839. BOOL PDynaLink::IsLoaded() const
  840. {
  841.   return _hDLL != NULL;
  842. }
  843. BOOL PDynaLink::GetFunction(PINDEX index, Function & func)
  844. {
  845.   if (_hDLL == NULL)
  846.     return FALSE;
  847.   FARPROC p = GetProcAddress(_hDLL, (LPSTR)(DWORD)LOWORD(index));
  848.   if (p == NULL)
  849.     return FALSE;
  850.   func = (Function)p;
  851.   return TRUE;
  852. }
  853. BOOL PDynaLink::GetFunction(const PString & name, Function & func)
  854. {
  855.   if (_hDLL == NULL)
  856.     return FALSE;
  857.   FARPROC p = GetProcAddress(_hDLL, name);
  858.   if (p == NULL)
  859.     return FALSE;
  860.   func = (Function)p;
  861.   return TRUE;
  862. }
  863. // End Of File ///////////////////////////////////////////////////////////////