Annotation of ntddk/src/krnldbg/kdapis/dbgkdapi.c, revision 1.1

1.1     ! root        1: #include "givit.h"
        !             2: 
        !             3: 
        !             4: extern HANDLE PipeRead;         // see DbgKdpKbdPollThread
        !             5: extern HANDLE PipeWrite;
        !             6: extern ULONG  NumberProcessors;
        !             7: static USHORT LastProcessorToPrint = -1;
        !             8: 
        !             9: UCHAR DbgKdpPacketLeader[4] = {
        !            10:         PACKET_LEADER_BYTE,
        !            11:         PACKET_LEADER_BYTE,
        !            12:         PACKET_LEADER_BYTE,
        !            13:         PACKET_LEADER_BYTE
        !            14:         };
        !            15: 
        !            16: //
        !            17: // DbgKdpCmdCanceled indicates the fact that the current kd command has
        !            18: // been canceled by user (using ctrl-C.)  With the Packet Id controlling
        !            19: // the packet exchange, the Ctrl-C has to be handled in controlled manner.
        !            20: // At each end of DbgKdpXXXX routine, we will check for this flag.  If the
        !            21: // command has been canceled, a longjmp will be performed to transfer control
        !            22: // back to kd prompt.
        !            23: //
        !            24: 
        !            25: BOOLEAN DbgKdpCmdCanceled = FALSE;
        !            26: 
        !            27: #ifdef DBG
        !            28: BOOLEAN KdDebug = FALSE;
        !            29: #endif
        !            30: 
        !            31: BOOLEAN KdResync = FALSE;
        !            32: UCHAR PrintBuf[PACKET_MAX_SIZE];
        !            33: 
        !            34: #define CONTROL_B   2
        !            35: #define CONTROL_D   4
        !            36: #define CONTROL_R   18
        !            37: #define CONTROL_V   22
        !            38: 
        !            39: ULONG DbgKdpPacketExpected;     // ID for expected incoming packet
        !            40: ULONG DbgKdpNextPacketToSend;   // ID for Next packet to send
        !            41: extern VOID DbgKdpSynchronizeTarget ( VOID );
        !            42: 
        !            43: //++
        !            44: //
        !            45: // VOID
        !            46: // DbgKdpWaitPacketForever (
        !            47: //     IN ULONG PacketType,
        !            48: //     IN PVOID Buffer
        !            49: //     )
        !            50: //
        !            51: // Routine Description:
        !            52: //
        !            53: //     This macro is invoked to wait for specifi type of message without
        !            54: //     timeout.
        !            55: //
        !            56: // Arguments:
        !            57: //
        !            58: //     PacketType - Type of the message we are expecting.
        !            59: //
        !            60: //     Buffer - Buffer to store the message.
        !            61: //
        !            62: // Return Value:
        !            63: //
        !            64: //     None.
        !            65: //
        !            66: //--
        !            67: 
        !            68: #define DbgKdpWaitPacketForever( PacketType, Buffer) {         \
        !            69:         BOOLEAN rc;                                            \
        !            70:         do {                                                   \
        !            71:             rc = DbgKdpWaitForPacket(                          \
        !            72:                          PacketType,                           \
        !            73:                          Buffer                                \
        !            74:                          );                                    \
        !            75:         } while ( rc == FALSE);                                \
        !            76: }
        !            77: 
        !            78: DWORD
        !            79: DbgKdConnectAndInitialize(
        !            80:     )
        !            81: {
        !            82: 
        !            83:     DWORD BytesWritten;
        !            84:     BOOL rc;
        !            85:     USHORT Length;
        !            86: 
        !            87:     //
        !            88:     // Initialize comport, packet queue and start the packet receiving
        !            89:     // thread.
        !            90:     //
        !            91: 
        !            92:     DbgKdpInitComPort(0L);
        !            93:     DbgKdpPacketExpected = INITIAL_PACKET_ID;
        !            94:     DbgKdpNextPacketToSend = INITIAL_PACKET_ID;
        !            95: 
        !            96:     DbgKdpStartThreads();
        !            97: 
        !            98:     return ERROR_SUCCESS;
        !            99: }
        !           100: 
        !           101: VOID
        !           102: DbgKdpHandlePromptString(
        !           103:     IN PDBGKD_DEBUG_IO IoMessage
        !           104:     )
        !           105: {
        !           106:     PUCHAR IoData;
        !           107:     DWORD i;
        !           108:     DWORD j;
        !           109:     BOOL rc;
        !           110:     UCHAR c;
        !           111:     PUCHAR d;
        !           112: 
        !           113:     IoData = (PUCHAR)(IoMessage+1);
        !           114: 
        !           115:     DbgKdpPrint(IoMessage->Processor,
        !           116:                 IoData,
        !           117:                 (USHORT)IoMessage->u.GetString.LengthOfPromptString
        !           118:                 );
        !           119: 
        !           120:     //
        !           121:     // read the prompt data
        !           122:     //
        !           123: 
        !           124:     j = 0;
        !           125:     d = IoData;
        !           126:     rc = DbgKdpGetConsoleByte(&c, 1, &i);
        !           127: 
        !           128:     while ( rc == TRUE &&
        !           129:             i == 1 &&
        !           130:             j < (USHORT)IoMessage->u.GetString.LengthOfStringRead) {
        !           131: 
        !           132:         if ( c == '\r' ) {
        !           133:             *d++ = '\0';
        !           134:             j++;
        !           135:         } else if ( c == '\n' ) {
        !           136:             *d++ = '\0';
        !           137:             j++;
        !           138:             break;
        !           139:         } else {
        !           140:             *d++ = c;
        !           141:             j++;
        !           142:         }
        !           143:         rc = DbgKdpGetConsoleByte(&c, 1, &i);
        !           144:     }
        !           145: 
        !           146:     LastProcessorToPrint = -1;
        !           147:     if ( j < (USHORT)IoMessage->u.GetString.LengthOfStringRead ) {
        !           148:         IoMessage->u.GetString.LengthOfStringRead = j;
        !           149:     }
        !           150: 
        !           151:     //
        !           152:     // Send data to the debugger-target
        !           153:     //
        !           154: 
        !           155:     DbgKdpWritePacket(
        !           156:         IoMessage,
        !           157:         sizeof(*IoMessage),
        !           158:         PACKET_TYPE_KD_DEBUG_IO,
        !           159:         IoData,
        !           160:         (USHORT)IoMessage->u.GetString.LengthOfStringRead
        !           161:         );
        !           162: }
        !           163: 
        !           164: VOID
        !           165: DbgKdpPrint(
        !           166:     IN USHORT Processor,
        !           167:     IN PUCHAR String,
        !           168:     IN USHORT StringLength
        !           169:     )
        !           170: {
        !           171:     DWORD i;
        !           172:     DWORD j;
        !           173:     UCHAR c;
        !           174:     PUCHAR d;
        !           175:     static USHORT LastProcessor = -1;
        !           176: 
        !           177:     assert(StringLength < PACKET_MAX_SIZE - 2);
        !           178: 
        !           179:     d = PrintBuf;
        !           180:     if (NumberProcessors > 1  &&  Processor != LastProcessorToPrint) {
        !           181:         assert(Processor < 8);
        !           182:         LastProcessorToPrint = Processor;
        !           183:         *d++ = (UCHAR)((UCHAR)Processor + '0');
        !           184:         *d++ = ':';
        !           185:         j = 2;
        !           186:     } else {
        !           187:         j = 0;
        !           188:     }
        !           189:     for(i=0;i<StringLength;i++) {
        !           190:         c = *(String+i);
        !           191:         if ( c == '\n' ) {
        !           192:             LastProcessorToPrint = -1;
        !           193:             *d++ = '\n';
        !           194:             *d++ = '\r';
        !           195:             j += 2;
        !           196:         } else {
        !           197:             if ( c ) {
        !           198:                 *d++ = c;
        !           199:                 j++;
        !           200:                 }
        !           201:             }
        !           202:         }
        !           203: 
        !           204:     //
        !           205:     // print the string. someday this should probably
        !           206:     // be a callout.
        !           207: 
        !           208:     WriteFile(ConsoleOutputHandle,PrintBuf,j,&i,NULL);
        !           209: }
        !           210: 
        !           211: DWORD
        !           212: DbgKdWaitStateChange(
        !           213:     OUT PDBGKD_WAIT_STATE_CHANGE StateChange,
        !           214:     OUT PVOID Buffer,
        !           215:     IN ULONG BufferLength
        !           216:     )
        !           217: 
        !           218: /*++
        !           219: 
        !           220: Routine Description:
        !           221: 
        !           222:     This function causes the calling user interface to wait for a state
        !           223:     change to occur in the system being debugged.  Once a state change
        !           224:     occurs, the user interface can either continue the system using
        !           225:     DbgKdContinue, or it can manipulate system state using anyone of the
        !           226:     DbgKd state manipulation APIs.
        !           227: 
        !           228: Arguments:
        !           229: 
        !           230:     StateChange - Supplies the address of state change record that
        !           231:         will contain the state change information.
        !           232: 
        !           233:     Buffer - Supplies the address of a buffer that returns additional
        !           234:         information.
        !           235: 
        !           236:     BufferLength - Supplies the length of Buffer.
        !           237: 
        !           238: Return Value:
        !           239: 
        !           240:     ERROR_SUCCESS - A state change occured. Valid state change information
        !           241:         was returned.
        !           242: 
        !           243: --*/
        !           244: 
        !           245: {
        !           246: 
        !           247:     PDBGKD_WAIT_STATE_CHANGE LocalStateChange;
        !           248:     DWORD st;
        !           249:     UCHAR   *pt;
        !           250: 
        !           251:     st = ERROR_INVALID_FUNCTION;
        !           252:     while ( st != ERROR_SUCCESS ) {
        !           253: 
        !           254:         //
        !           255:         // Waiting for a state change message. Copy the message to the callers
        !           256:         // buffer, and then free the packet entry.
        !           257:         //
        !           258: 
        !           259:         DbgKdpWaitPacketForever(
        !           260:                 PACKET_TYPE_KD_STATE_CHANGE,
        !           261:                 &LocalStateChange
        !           262:                 );
        !           263:         LocalStateChange = (PDBGKD_WAIT_STATE_CHANGE)DbgKdpPacket;
        !           264:         st = ERROR_SUCCESS;
        !           265:         assert(StateChange);
        !           266:         *StateChange = *LocalStateChange;
        !           267: 
        !           268:         switch ( (USHORT) StateChange->NewState ) {
        !           269:             case DbgKdExceptionStateChange:
        !           270:                 break;
        !           271:             case DbgKdLoadSymbolsStateChange:
        !           272:                 if ( BufferLength < LocalStateChange->u.LoadSymbols.PathNameLength ) {
        !           273:                     st = ERROR_MORE_DATA;
        !           274:                 } else {
        !           275:                     pt = ((UCHAR *) LocalStateChange) + PacketHeader.ByteCount -
        !           276:                          (int)LocalStateChange->u.LoadSymbols.PathNameLength;
        !           277:                     memcpy(Buffer, pt,
        !           278:                          (int)LocalStateChange->u.LoadSymbols.PathNameLength);
        !           279:                 }
        !           280:                 break;
        !           281:             default:
        !           282:                 assert(FALSE);
        !           283:         }
        !           284:         return st;
        !           285:     }
        !           286: }
        !           287: 
        !           288: DWORD
        !           289: DbgKdContinue (
        !           290:     IN DWORD ContinueStatus
        !           291:     )
        !           292: 
        !           293: /*++
        !           294: 
        !           295: Routine Description:
        !           296: 
        !           297:     Continuing a system that previously reported a state change causes
        !           298:     the system to continue executiontion using the context in effect at
        !           299:     the time the state change was reported (of course this context could
        !           300:     have been modified using the DbgKd state manipulation APIs).
        !           301: 
        !           302: Arguments:
        !           303: 
        !           304:     ContinueStatus - Supplies the continuation status to the thread
        !           305:         being continued.  Valid values for this are
        !           306:         DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED
        !           307:         or DBG_CONTINUE.
        !           308: 
        !           309: Return Value:
        !           310: 
        !           311:     ERROR_SUCCESS - Successful call to DbgUiContinue
        !           312: 
        !           313:     ERROR_INVALID_PARAMETER - An invalid continue status or was
        !           314:         specified.
        !           315: 
        !           316: --*/
        !           317: 
        !           318: {
        !           319:     DBGKD_MANIPULATE_STATE m;
        !           320:     PDBGKD_CONTINUE a = &m.u.Continue;
        !           321:     DWORD st;
        !           322: 
        !           323:     if ( ContinueStatus == DBG_EXCEPTION_HANDLED ||
        !           324:          ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
        !           325:          ContinueStatus == DBG_CONTINUE ) {
        !           326: 
        !           327:         m.ApiNumber = DbgKdContinueApi;
        !           328:         m.ReturnStatus = ContinueStatus;
        !           329: 
        !           330:         a->ContinueStatus = ContinueStatus;
        !           331:         DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
        !           332:         st = ERROR_SUCCESS;
        !           333:         }
        !           334:     else {
        !           335:         st = ERROR_INVALID_PARAMETER;
        !           336:         }
        !           337: 
        !           338:     return st;
        !           339: }
        !           340: 
        !           341: 
        !           342: DWORD
        !           343: DbgKdContinue2 (
        !           344:     IN DWORD ContinueStatus,
        !           345:     IN DBGKD_CONTROL_SET ControlSet
        !           346:     )
        !           347: 
        !           348: /*++
        !           349: 
        !           350: Routine Description:
        !           351: 
        !           352:     Continuing a system that previously reported a state change causes
        !           353:     the system to continue executiontion using the context in effect at
        !           354:     the time the state change was reported, modified by the values set
        !           355:     in the ControlSet structure.  (And, of course, the context could have
        !           356:     been modified by used the DbgKd state manipulation APIs.)
        !           357: 
        !           358: Arguments:
        !           359: 
        !           360:     ContinueStatus - Supplies the continuation status to the thread
        !           361:         being continued.  Valid values for this are
        !           362:         DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED
        !           363:         or DBG_CONTINUE.
        !           364: 
        !           365:     ControlSet - Supplies a pointer to a structure containing the machine
        !           366:         specific control data to set.  For the x86 this is the TraceFlag
        !           367:         and Dr7.
        !           368: 
        !           369: Return Value:
        !           370: 
        !           371:     ERROR_SUCCESS - Successful call to DbgUiContinue
        !           372: 
        !           373:     ERROR_INVALID_PARAMETER - An invalid continue status or was
        !           374:         specified.
        !           375: 
        !           376: --*/
        !           377: 
        !           378: {
        !           379:     DBGKD_MANIPULATE_STATE m;
        !           380:     DWORD st;
        !           381: 
        !           382:     if ( ContinueStatus == DBG_EXCEPTION_HANDLED ||
        !           383:          ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
        !           384:          ContinueStatus == DBG_CONTINUE ) {
        !           385: 
        !           386:         m.ApiNumber = DbgKdContinueApi2;
        !           387:         m.ReturnStatus = ContinueStatus;
        !           388: 
        !           389:         m.u.Continue2.ContinueStatus = ContinueStatus;
        !           390:         m.u.Continue2.ControlSet = ControlSet;
        !           391: 
        !           392:         DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
        !           393:         st = ERROR_SUCCESS;
        !           394: 
        !           395:     } else {
        !           396:         st = ERROR_INVALID_PARAMETER;
        !           397:     }
        !           398: 
        !           399:     return st;
        !           400: }
        !           401: 
        !           402: DWORD
        !           403: DbgKdReadVirtualMemory(
        !           404:     IN PVOID TargetBaseAddress,
        !           405:     OUT PVOID UserInterfaceBuffer,
        !           406:     IN ULONG TransferCount,
        !           407:     OUT PULONG ActualBytesRead OPTIONAL
        !           408:     )
        !           409: 
        !           410: /*++
        !           411: 
        !           412: Routine Description:
        !           413: 
        !           414:     This function reads the specified data from the system being debugged
        !           415:     using the current mapping of the processor.
        !           416: 
        !           417: Arguments:
        !           418: 
        !           419:     TargetBaseAddress - Supplies the base address of the memory to read
        !           420:         from the system being debugged.  The virtual address is in terms
        !           421:         of the current mapping for the processor that reported the last
        !           422:         state change.  Until we figure out how to do this differently,
        !           423:         the virtual address must refer to a valid page (although it does
        !           424:         not necesserily have to be in the TB).
        !           425: 
        !           426:     UserInterfaceBuffer - Supplies the address of the buffer in the user
        !           427:         interface that data read is to be placed.
        !           428: 
        !           429:     TransferCount - Specifies the number of bytes to read.
        !           430: 
        !           431:     ActualBytesRead - An optional parameter that if supplied, returns
        !           432:         the number of bytes actually read.
        !           433: 
        !           434: Return Value:
        !           435: 
        !           436:     ERROR_SUCCESS - The specified read occured.
        !           437: 
        !           438:     ERROR_MORE_DATA - A read that is to large was specified.
        !           439: 
        !           440:     ERROR_NO_ACCESS - The TargetBaseAddress/TransferCount
        !           441:         parameters refers to invalid virtual memory.
        !           442: 
        !           443:     !ERROR_SUCCESS - TBD
        !           444: 
        !           445: --*/
        !           446: 
        !           447: {
        !           448:     DBGKD_MANIPULATE_STATE m;
        !           449:     PDBGKD_MANIPULATE_STATE Reply;
        !           450:     PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
        !           451:     DWORD st;
        !           452:     BOOLEAN rc;
        !           453: 
        !           454:     if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
        !           455:         return ERROR_MORE_DATA;
        !           456:         }
        !           457: 
        !           458:     //
        !           459:     // Format state manipulate message
        !           460:     //
        !           461: 
        !           462:     m.ApiNumber = DbgKdReadVirtualMemoryApi;
        !           463:     m.ReturnStatus = STATUS_PENDING;
        !           464:     a->TargetBaseAddress = TargetBaseAddress;
        !           465:     a->TransferCount = TransferCount;
        !           466:     a->ActualBytesRead = 0L;
        !           467: 
        !           468:     //
        !           469:     // Send the message and then wait for reply
        !           470:     //
        !           471: 
        !           472:     do {
        !           473:         DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
        !           474: 
        !           475:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
        !           476:                                  &Reply
        !           477:                                  );
        !           478:     } while (rc == FALSE);
        !           479: 
        !           480:     //
        !           481:     // If this is not a ReadMemory response than protocol is screwed up.
        !           482:     // assert that protocol is ok.
        !           483:     //
        !           484: 
        !           485:     st = Reply->ReturnStatus;
        !           486:     assert(Reply->ApiNumber == DbgKdReadVirtualMemoryApi);
        !           487: 
        !           488:     //
        !           489:     // Reset message address to reply.
        !           490:     //
        !           491: 
        !           492:     a = &Reply->u.ReadMemory;
        !           493:     assert(a->ActualBytesRead <= TransferCount);
        !           494: 
        !           495:     //
        !           496:     // Return actual bytes read, and then transfer the bytes
        !           497:     //
        !           498: 
        !           499:     if (ActualBytesRead) {
        !           500:         *ActualBytesRead = a->ActualBytesRead;
        !           501:     }
        !           502:     st = Reply->ReturnStatus;
        !           503: 
        !           504:     //
        !           505:     // Since read response data follows message, Reply+1 should point
        !           506:     // at the data
        !           507:     //
        !           508: 
        !           509:     memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead);
        !           510: 
        !           511:     return st;
        !           512: }
        !           513: 
        !           514: 
        !           515: 
        !           516: DWORD
        !           517: DbgKdWriteVirtualMemory(
        !           518:     IN PVOID TargetBaseAddress,
        !           519:     OUT PVOID UserInterfaceBuffer,
        !           520:     IN ULONG TransferCount,
        !           521:     OUT PULONG ActualBytesWritten OPTIONAL
        !           522:     )
        !           523: 
        !           524: /*++
        !           525: 
        !           526: Routine Description:
        !           527: 
        !           528:     This function writes the specified data to the system being debugged
        !           529:     using the current mapping of the processor.
        !           530: 
        !           531: Arguments:
        !           532: 
        !           533:     TargetBaseAddress - Supplies the base address of the memory to be written
        !           534:         into the system being debugged.  The virtual address is in terms
        !           535:         of the current mapping for the processor that reported the last
        !           536:         state change.  Until we figure out how to do this differently,
        !           537:         the virtual address must refer to a valid page (although it does
        !           538:         not necesserily have to be in the TB).
        !           539: 
        !           540:     UserInterfaceBuffer - Supplies the address of the buffer in the user
        !           541:         interface that contains the data to be written.
        !           542: 
        !           543:     TransferCount - Specifies the number of bytes to write.
        !           544: 
        !           545:     ActualBytesWritten - An optional parameter that if supplied, returns
        !           546:         the number of bytes actually written.
        !           547: 
        !           548: Return Value:
        !           549: 
        !           550:     ERROR_SUCCESS - The specified read occured.
        !           551: 
        !           552:     ERROR_MORE_DATA - A read that is to large was specified.
        !           553: 
        !           554:     ERROR_NO_ACCESS - The TargetBaseAddress/TransferCount
        !           555:         parameters refers to invalid virtual memory.
        !           556: 
        !           557:     !ERROR_SUCCESS - TBD
        !           558: 
        !           559: --*/
        !           560: 
        !           561: {
        !           562:     DBGKD_MANIPULATE_STATE m;
        !           563:     PDBGKD_MANIPULATE_STATE Reply;
        !           564:     PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
        !           565:     DWORD st;
        !           566:     BOOLEAN rc;
        !           567: 
        !           568:     if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
        !           569:         return ERROR_MORE_DATA;
        !           570:         }
        !           571: 
        !           572:     //
        !           573:     // Format state manipulate message
        !           574:     //
        !           575: 
        !           576:     m.ApiNumber = DbgKdWriteVirtualMemoryApi;
        !           577:     m.ReturnStatus = STATUS_PENDING;
        !           578:     a->TargetBaseAddress = TargetBaseAddress;
        !           579:     a->TransferCount = TransferCount;
        !           580:     a->ActualBytesWritten = 0L;
        !           581: 
        !           582:     //
        !           583:     // Send the message and data to write and then wait for reply
        !           584:     //
        !           585: 
        !           586:     do {
        !           587:         DbgKdpWritePacket(
        !           588:             &m,
        !           589:             sizeof(m),
        !           590:             PACKET_TYPE_KD_STATE_MANIPULATE,
        !           591:             UserInterfaceBuffer,
        !           592:             (USHORT)TransferCount
        !           593:             );
        !           594:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
        !           595:                                  &Reply
        !           596:                                  );
        !           597:     } while (rc == FALSE);
        !           598: 
        !           599:     //
        !           600:     // If this is not a WriteMemory response than protocol is screwed up.
        !           601:     // assert that protocol is ok.
        !           602:     //
        !           603: 
        !           604:     st = Reply->ReturnStatus;
        !           605:     assert(Reply->ApiNumber == DbgKdWriteVirtualMemoryApi);
        !           606: 
        !           607:     //
        !           608:     // Reset message address to reply.
        !           609:     //
        !           610: 
        !           611:     a = &Reply->u.WriteMemory;
        !           612:     assert(a->ActualBytesWritten <= TransferCount);
        !           613: 
        !           614:     //
        !           615:     // Return actual bytes written
        !           616:     //
        !           617: 
        !           618:     if (ActualBytesWritten) {
        !           619:         *ActualBytesWritten = a->ActualBytesWritten;
        !           620:     }
        !           621:     st = Reply->ReturnStatus;
        !           622: 
        !           623:     return st;
        !           624: }
        !           625: 
        !           626: DWORD
        !           627: DbgKdReadControlSpace(
        !           628:     IN USHORT Processor,
        !           629:     IN PVOID TargetBaseAddress,
        !           630:     OUT PVOID UserInterfaceBuffer,
        !           631:     IN ULONG TransferCount,
        !           632:     OUT PULONG ActualBytesRead OPTIONAL
        !           633:     )
        !           634: 
        !           635: /*++
        !           636: 
        !           637: Routine Description:
        !           638: 
        !           639:     This function reads the specified data from the control space of
        !           640:     the system being debugged.
        !           641: 
        !           642:     Control space is processor dependent. TargetBaseAddress is mapped
        !           643:     to control space in a processor/implementation defined manner.
        !           644: 
        !           645: Arguments:
        !           646: 
        !           647:     Processor - Supplies the processor whoes control space is desired.
        !           648: 
        !           649:     TargetBaseAddress - Supplies the base address in control space to
        !           650:         read. This address is interpreted in an implementation defined
        !           651:         manner.
        !           652: 
        !           653: 
        !           654:         On x86, control space is a per-processor area which contains:
        !           655: 
        !           656:             Current Context     (CONTEXT)
        !           657:             Special Registers   (KSPECIAL_REGISTERS)
        !           658: 
        !           659:             This means that to read the special registers:
        !           660: 
        !           661:                 DbgKdReadControlSpace(
        !           662:                     NtsdCurrentProcessor,
        !           663:                     (PVOID)sizeof(CONTEXT),
        !           664:                     (PVOID)&SpecialRegContext,
        !           665:                     sizeof(KSPECIAL_REGISTERS),
        !           666:                     &cBytesRead
        !           667:                     );
        !           668: 
        !           669:             The above will read the special registers of the current processor
        !           670:             since the control space address is sizeof(CONTEXT)
        !           671: 
        !           672:         On MIPS, control space addresses are used to address the translation
        !           673:         buffer.
        !           674: 
        !           675:     UserInterfaceBuffer - Supplies the address of the buffer in the user
        !           676:         interface that data read is to be placed.
        !           677: 
        !           678:     TransferCount - Specifies the number of bytes to read.
        !           679: 
        !           680:     ActualBytesRead - An optional parameter that if supplied, returns
        !           681:         the number of bytes actually read.
        !           682: 
        !           683: Return Value:
        !           684: 
        !           685:     ERROR_SUCCESS - The specified read occured.
        !           686: 
        !           687:     ERROR_MORE_DATA - A read that is to large was specified.
        !           688: 
        !           689:     !ERROR_SUCCESS - TBD
        !           690: 
        !           691: --*/
        !           692: 
        !           693: {
        !           694:     DBGKD_MANIPULATE_STATE m;
        !           695:     PDBGKD_MANIPULATE_STATE Reply;
        !           696:     PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
        !           697:     DWORD st;
        !           698:     BOOLEAN rc;
        !           699: 
        !           700:     if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
        !           701:         return ERROR_MORE_DATA;
        !           702:         }
        !           703: 
        !           704:     //
        !           705:     // Format state manipulate message
        !           706:     //
        !           707: 
        !           708:     m.ApiNumber = DbgKdReadControlSpaceApi;
        !           709:     m.ReturnStatus = STATUS_PENDING;
        !           710:     m.Processor = Processor;
        !           711:     a->TargetBaseAddress = TargetBaseAddress;
        !           712:     a->TransferCount = TransferCount;
        !           713:     a->ActualBytesRead = 0L;
        !           714: 
        !           715:     //
        !           716:     // Send the message and then wait for reply
        !           717:     //
        !           718: 
        !           719:     do {
        !           720:         DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
        !           721: 
        !           722:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !           723: 
        !           724:     } while (rc == FALSE);
        !           725: 
        !           726:     //
        !           727:     // If this is not a ReadControl response than protocol is screwed up.
        !           728:     // assert that protocol is ok.
        !           729:     //
        !           730: 
        !           731:     st = Reply->ReturnStatus;
        !           732:     assert(Reply->ApiNumber == DbgKdReadControlSpaceApi);
        !           733: 
        !           734:     //
        !           735:     // Reset message address to reply.
        !           736:     //
        !           737: 
        !           738:     a = &Reply->u.ReadMemory;
        !           739:     assert(a->ActualBytesRead <= TransferCount);
        !           740: 
        !           741:     //
        !           742:     // Return actual bytes read, and then transfer the bytes
        !           743:     //
        !           744: 
        !           745:     if (ActualBytesRead) {
        !           746:         *ActualBytesRead = a->ActualBytesRead;
        !           747:     }
        !           748:     st = Reply->ReturnStatus;
        !           749: 
        !           750:     //
        !           751:     // Since read response data follows message, Reply+1 should point
        !           752:     // at the data
        !           753:     //
        !           754: 
        !           755:     memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead);
        !           756: 
        !           757:     return st;
        !           758: }
        !           759: 
        !           760: 
        !           761: 
        !           762: DWORD
        !           763: DbgKdWriteControlSpace(
        !           764:     IN USHORT Processor,
        !           765:     IN PVOID TargetBaseAddress,
        !           766:     OUT PVOID UserInterfaceBuffer,
        !           767:     IN ULONG TransferCount,
        !           768:     OUT PULONG ActualBytesWritten OPTIONAL
        !           769:     )
        !           770: 
        !           771: /*++
        !           772: 
        !           773: Routine Description:
        !           774: 
        !           775:     This function writes the specified data to control space on the system
        !           776:     being debugged.
        !           777: 
        !           778:     Control space is processor dependent. TargetBaseAddress is mapped
        !           779:     to control space in a processor/implementation defined manner.
        !           780: 
        !           781: Arguments:
        !           782: 
        !           783:     Processor - Supplies the processor whoes control space is desired.
        !           784: 
        !           785:     TargetBaseAddress - Supplies the base address in control space to be
        !           786:         written.
        !           787: 
        !           788:     UserInterfaceBuffer - Supplies the address of the buffer in the user
        !           789:         interface that contains the data to be written.
        !           790: 
        !           791:     TransferCount - Specifies the number of bytes to write.
        !           792: 
        !           793:     ActualBytesWritten - An optional parameter that if supplied, returns
        !           794:         the number of bytes actually written.
        !           795: 
        !           796: Return Value:
        !           797: 
        !           798:     ERROR_SUCCESS - The specified read occured.
        !           799: 
        !           800:     ERROR_MORE_DATA - A read that is to large was specified.
        !           801: 
        !           802:     !ERROR_SUCCESS - TBD
        !           803: 
        !           804: --*/
        !           805: 
        !           806: {
        !           807:     DBGKD_MANIPULATE_STATE m;
        !           808:     PDBGKD_MANIPULATE_STATE Reply;
        !           809:     PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
        !           810:     DWORD st;
        !           811:     BOOLEAN rc;
        !           812: 
        !           813:     if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
        !           814:         return ERROR_MORE_DATA;
        !           815:         }
        !           816: 
        !           817:     //
        !           818:     // Format state manipulate message
        !           819:     //
        !           820: 
        !           821:     m.ApiNumber = DbgKdWriteControlSpaceApi;
        !           822:     m.ReturnStatus = STATUS_PENDING;
        !           823:     m.Processor = Processor;
        !           824:     a->TargetBaseAddress = TargetBaseAddress;
        !           825:     a->TransferCount = TransferCount;
        !           826:     a->ActualBytesWritten = 0L;
        !           827: 
        !           828:     //
        !           829:     // Send the message and data to write and then wait for reply
        !           830:     //
        !           831: 
        !           832:     do {
        !           833:         DbgKdpWritePacket(
        !           834:             &m,
        !           835:             sizeof(m),
        !           836:             PACKET_TYPE_KD_STATE_MANIPULATE,
        !           837:             UserInterfaceBuffer,
        !           838:             (USHORT)TransferCount
        !           839:             );
        !           840: 
        !           841:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !           842:     } while (rc == FALSE);
        !           843: 
        !           844:     //
        !           845:     // If this is not a WriteControl response than protocol is screwed up.
        !           846:     // assert that protocol is ok.
        !           847:     //
        !           848: 
        !           849:     st = Reply->ReturnStatus;
        !           850:     assert(Reply->ApiNumber == DbgKdWriteControlSpaceApi);
        !           851: 
        !           852:     //
        !           853:     // Reset message address to reply.
        !           854:     //
        !           855: 
        !           856:     a = &Reply->u.WriteMemory;
        !           857:     assert(a->ActualBytesWritten <= TransferCount);
        !           858: 
        !           859:     //
        !           860:     // Return actual bytes written
        !           861:     //
        !           862: 
        !           863:     *ActualBytesWritten = a->ActualBytesWritten;
        !           864:     st = Reply->ReturnStatus;
        !           865: 
        !           866:     return st;
        !           867: }
        !           868: 
        !           869: 
        !           870: DWORD
        !           871: DbgKdGetContext(
        !           872:     IN USHORT Processor,
        !           873:     IN OUT PCONTEXT Context
        !           874:     )
        !           875: 
        !           876: /*++
        !           877: 
        !           878: Routine Description:
        !           879: 
        !           880:     This function reads the context from the system being debugged.
        !           881:     The ContextFlags field determines how much context is read.
        !           882: 
        !           883: Arguments:
        !           884: 
        !           885:     Processor - Supplies a processor number to get context from.
        !           886: 
        !           887:     Context - On input, the ContextFlags field controls what portions of
        !           888:         the context record the caller as interested in reading.  On
        !           889:         output, the context record returns the current context for the
        !           890:         processor that reported the last state change.
        !           891: 
        !           892: Return Value:
        !           893: 
        !           894:     ERROR_SUCCESS - The specified get context occured.
        !           895: 
        !           896:     !ERROR_SUCCESS - TBD
        !           897: 
        !           898: --*/
        !           899: 
        !           900: {
        !           901:     DBGKD_MANIPULATE_STATE m;
        !           902:     PDBGKD_MANIPULATE_STATE Reply;
        !           903:     PDBGKD_GET_CONTEXT a = &m.u.GetContext;
        !           904:     DWORD st;
        !           905:     BOOLEAN rc;
        !           906: 
        !           907:     //
        !           908:     // Format state manipulate message
        !           909:     //
        !           910: 
        !           911:     m.ApiNumber = DbgKdGetContextApi;
        !           912:     m.ReturnStatus = STATUS_PENDING;
        !           913:     m.Processor = Processor;
        !           914:     a->ContextFlags = Context->ContextFlags;
        !           915: 
        !           916:     //
        !           917:     // Send the message and then wait for reply
        !           918:     //
        !           919: 
        !           920:     do {
        !           921:         DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
        !           922:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !           923:     } while (rc == FALSE);
        !           924: 
        !           925:     //
        !           926:     // If this is not a GetContext response than protocol is screwed up.
        !           927:     // assert that protocol is ok.
        !           928:     //
        !           929: 
        !           930:     st = Reply->ReturnStatus;
        !           931:     assert(Reply->ApiNumber == DbgKdGetContextApi);
        !           932: 
        !           933:     //
        !           934:     // Reset message address to reply.
        !           935:     //
        !           936: 
        !           937:     a = &Reply->u.GetContext;
        !           938:     st = Reply->ReturnStatus;
        !           939: 
        !           940:     //
        !           941:     // Since get context response data follows message, Reply+1 should point
        !           942:     // at the data
        !           943:     //
        !           944: 
        !           945:     memcpy(Context, Reply+1, sizeof(*Context));
        !           946: 
        !           947:     return st;
        !           948: }
        !           949: 
        !           950: 
        !           951: 
        !           952: DWORD
        !           953: DbgKdSetContext(
        !           954:     IN USHORT Processor,
        !           955:     IN PCONTEXT Context
        !           956:     )
        !           957: 
        !           958: /*++
        !           959: 
        !           960: Routine Description:
        !           961: 
        !           962:     This function writes the specified context to the system being debugged.
        !           963: 
        !           964: Arguments:
        !           965: 
        !           966:     Processor - Supplies a processor number to set the context to.
        !           967: 
        !           968:     Context - Supplies a context record used to set the context for the
        !           969:         processor that reported the last state change.  Only the
        !           970:         portions of the context indicated by the ContextFlags field are
        !           971:         actually written.
        !           972: 
        !           973: 
        !           974: Return Value:
        !           975: 
        !           976:     ERROR_SUCCESS - The specified set context occured.
        !           977: 
        !           978:     !ERROR_SUCCESS - TBD
        !           979: 
        !           980: --*/
        !           981: 
        !           982: {
        !           983:     DBGKD_MANIPULATE_STATE m;
        !           984:     PDBGKD_MANIPULATE_STATE Reply;
        !           985:     PDBGKD_SET_CONTEXT a = &m.u.SetContext;
        !           986:     DWORD st;
        !           987:     BOOLEAN rc;
        !           988: 
        !           989:     //
        !           990:     // Format state manipulate message
        !           991:     //
        !           992: 
        !           993:     m.ApiNumber = DbgKdSetContextApi;
        !           994:     m.ReturnStatus = STATUS_PENDING;
        !           995:     m.Processor = Processor;
        !           996:     a->ContextFlags = Context->ContextFlags;
        !           997: 
        !           998:     //
        !           999:     // Send the message and context and then wait for reply
        !          1000:     //
        !          1001: 
        !          1002:     do {
        !          1003:         DbgKdpWritePacket(
        !          1004:             &m,
        !          1005:             sizeof(m),
        !          1006:             PACKET_TYPE_KD_STATE_MANIPULATE,
        !          1007:             Context,
        !          1008:             sizeof(*Context)
        !          1009:             );
        !          1010:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !          1011:     } while (rc == FALSE);
        !          1012: 
        !          1013:     //
        !          1014:     // If this is not a SetContext response than protocol is screwed up.
        !          1015:     // assert that protocol is ok.
        !          1016:     //
        !          1017: 
        !          1018:     st = Reply->ReturnStatus;
        !          1019:     assert(Reply->ApiNumber == DbgKdSetContextApi);
        !          1020: 
        !          1021:     //
        !          1022:     // Reset message address to reply.
        !          1023:     //
        !          1024: 
        !          1025:     a = &Reply->u.SetContext;
        !          1026:     st = Reply->ReturnStatus;
        !          1027: 
        !          1028:     return st;
        !          1029: }
        !          1030: 
        !          1031: DWORD
        !          1032: DbgKdWriteBreakPoint(
        !          1033:     IN PVOID BreakPointAddress,
        !          1034:     OUT PULONG BreakPointHandle
        !          1035:     )
        !          1036: 
        !          1037: /*++
        !          1038: 
        !          1039: Routine Description:
        !          1040: 
        !          1041:     This function is used to write a breakpoint at the address specified.
        !          1042: 
        !          1043: 
        !          1044: Arguments:
        !          1045: 
        !          1046:     BreakPointAddress - Supplies the address that a breakpoint
        !          1047:         instruction is to be written.  This address is interpreted using
        !          1048:         the current mapping on the processor reporting the previous
        !          1049:         state change.  If the address refers to a page that is not
        !          1050:         valid, the the breakpoint is remembered by the system.  As each
        !          1051:         page is made valid, the system will check for pending
        !          1052:         breakpoints and install breakpoints as necessary.
        !          1053: 
        !          1054:     BreakPointHandle - Returns a handle to a breakpoint.  This handle
        !          1055:         may be used in a subsequent call to DbgKdRestoreBreakPoint.
        !          1056: 
        !          1057: Return Value:
        !          1058: 
        !          1059:     ERROR_SUCCESS - The specified breakpoint write occured.
        !          1060: 
        !          1061:     !ERROR_SUCCESS - TBD
        !          1062: 
        !          1063: 
        !          1064: --*/
        !          1065: 
        !          1066: {
        !          1067: 
        !          1068:     DBGKD_MANIPULATE_STATE m;
        !          1069:     PDBGKD_MANIPULATE_STATE Reply;
        !          1070:     PDBGKD_WRITE_BREAKPOINT a = &m.u.WriteBreakPoint;
        !          1071:     DWORD st;
        !          1072:     BOOLEAN rc;
        !          1073: 
        !          1074:     //
        !          1075:     // Format state manipulate message
        !          1076:     //
        !          1077: 
        !          1078:     m.ApiNumber = DbgKdWriteBreakPointApi;
        !          1079:     m.ReturnStatus = STATUS_PENDING;
        !          1080:     a->BreakPointAddress = BreakPointAddress;
        !          1081: 
        !          1082:     //
        !          1083:     // Send the message and context and then wait for reply
        !          1084:     //
        !          1085: 
        !          1086:     do {
        !          1087:         DbgKdpWritePacket(
        !          1088:             &m,
        !          1089:             sizeof(m),
        !          1090:             PACKET_TYPE_KD_STATE_MANIPULATE,
        !          1091:             NULL,
        !          1092:             0
        !          1093:             );
        !          1094: 
        !          1095:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !          1096:     } while (rc == FALSE);
        !          1097: 
        !          1098:     //
        !          1099:     // If this is not a WriteBreakPoint response than protocol is screwed up.
        !          1100:     // assert that protocol is ok.
        !          1101:     //
        !          1102: 
        !          1103:     st = Reply->ReturnStatus;
        !          1104:     assert(Reply->ApiNumber == DbgKdWriteBreakPointApi);
        !          1105: 
        !          1106:     //
        !          1107:     // Reset message address to reply.
        !          1108:     //
        !          1109: 
        !          1110:     a = &Reply->u.WriteBreakPoint;
        !          1111:     st = Reply->ReturnStatus;
        !          1112:     *BreakPointHandle = a->BreakPointHandle;
        !          1113: 
        !          1114:     return st;
        !          1115: }
        !          1116: 
        !          1117: DWORD
        !          1118: DbgKdRestoreBreakPoint(
        !          1119:     IN ULONG BreakPointHandle
        !          1120:     )
        !          1121: 
        !          1122: /*++
        !          1123: 
        !          1124: Routine Description:
        !          1125: 
        !          1126:     This function is used to restore a breakpoint to its original
        !          1127:     value.
        !          1128: 
        !          1129: Arguments:
        !          1130: 
        !          1131:     BreakPointHandle - Supplies a handle returned by
        !          1132:         DbgKdWriteBreakPoint.  This handle must refer to a valid
        !          1133:         address.  The contents of the address must also be a breakpoint
        !          1134:         instruction.  If both of these are true, then the original value
        !          1135:         at the breakpoint address is restored.
        !          1136: 
        !          1137: Return Value:
        !          1138: 
        !          1139:     ERROR_SUCCESS - The specified breakpoint restore occured.
        !          1140: 
        !          1141:     !ERROR_SUCCESS - TBD
        !          1142: 
        !          1143: --*/
        !          1144: 
        !          1145: {
        !          1146: 
        !          1147:     DBGKD_MANIPULATE_STATE m;
        !          1148:     PDBGKD_MANIPULATE_STATE Reply;
        !          1149:     PDBGKD_RESTORE_BREAKPOINT a = &m.u.RestoreBreakPoint;
        !          1150:     DWORD st;
        !          1151:     BOOLEAN rc;
        !          1152: 
        !          1153:     //
        !          1154:     // Format state manipulate message
        !          1155:     //
        !          1156: 
        !          1157:     m.ApiNumber = DbgKdRestoreBreakPointApi;
        !          1158:     m.ReturnStatus = STATUS_PENDING;
        !          1159:     a->BreakPointHandle = BreakPointHandle;
        !          1160: 
        !          1161:     //
        !          1162:     // Send the message and context and then wait for reply
        !          1163:     //
        !          1164: 
        !          1165:     do {
        !          1166:         DbgKdpWritePacket(
        !          1167:             &m,
        !          1168:             sizeof(m),
        !          1169:             PACKET_TYPE_KD_STATE_MANIPULATE,
        !          1170:             NULL,
        !          1171:             0
        !          1172:             );
        !          1173: 
        !          1174:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !          1175:     } while (rc == FALSE);
        !          1176: 
        !          1177:     //
        !          1178:     // If this is not a RestoreBreakPoint response than protocol is screwed up.
        !          1179:     // assert that protocol is ok.
        !          1180:     //
        !          1181: 
        !          1182:     st = Reply->ReturnStatus;
        !          1183:     assert(Reply->ApiNumber == DbgKdRestoreBreakPointApi);
        !          1184: 
        !          1185:     //
        !          1186:     // Reset message address to reply.
        !          1187:     //
        !          1188: 
        !          1189:     a = &Reply->u.RestoreBreakPoint;
        !          1190:     st = Reply->ReturnStatus;
        !          1191: 
        !          1192:     //
        !          1193:     // free the packet
        !          1194:     //
        !          1195: 
        !          1196:     return st;
        !          1197: }
        !          1198: 
        !          1199: DWORD
        !          1200: DbgKdReadIoSpace(
        !          1201:     IN PVOID IoAddress,
        !          1202:     OUT PVOID ReturnedData,
        !          1203:     IN ULONG DataSize
        !          1204:     )
        !          1205: 
        !          1206: /*++
        !          1207: 
        !          1208: Routine Description:
        !          1209: 
        !          1210:     This function is used read a byte, short, or long (1,2,4 bytes) from
        !          1211:     the specified I/O address.
        !          1212: 
        !          1213: Arguments:
        !          1214: 
        !          1215:     IoAddress - Supplies the Io address to read from.
        !          1216: 
        !          1217:     ReturnedData - Supplies the value read from the I/O address.
        !          1218: 
        !          1219:     DataSize - Supplies the size in bytes to read. Values of 1, 2, or
        !          1220:         4 are accepted.
        !          1221: 
        !          1222: Return Value:
        !          1223: 
        !          1224:     ERROR_SUCCESS - Data was successfully read from the I/O
        !          1225:         address.
        !          1226: 
        !          1227:     ERROR_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
        !          1228:         specified.
        !          1229: 
        !          1230:     !ERROR_SUCCESS - TBD
        !          1231: 
        !          1232: --*/
        !          1233: 
        !          1234: {
        !          1235: 
        !          1236:     DBGKD_MANIPULATE_STATE m;
        !          1237:     PDBGKD_MANIPULATE_STATE Reply;
        !          1238:     PDBGKD_READ_WRITE_IO a = &m.u.ReadWriteIo;
        !          1239:     DWORD st;
        !          1240:     BOOLEAN rc;
        !          1241: 
        !          1242:     switch ( DataSize ) {
        !          1243:         case 1:
        !          1244:         case 2:
        !          1245:         case 4:
        !          1246:             break;
        !          1247:         default:
        !          1248:             return ERROR_INVALID_PARAMETER;
        !          1249:         }
        !          1250: 
        !          1251:     //
        !          1252:     // Format state manipulate message
        !          1253:     //
        !          1254: 
        !          1255:     m.ApiNumber = DbgKdReadIoSpaceApi;
        !          1256:     m.ReturnStatus = STATUS_PENDING;
        !          1257: 
        !          1258:     a->DataSize = DataSize;
        !          1259:     a->IoAddress = IoAddress;
        !          1260: 
        !          1261:     //
        !          1262:     // Send the message and then wait for reply
        !          1263:     //
        !          1264: 
        !          1265:     do {
        !          1266:         DbgKdpWritePacket(
        !          1267:             &m,
        !          1268:             sizeof(m),
        !          1269:             PACKET_TYPE_KD_STATE_MANIPULATE,
        !          1270:             NULL,
        !          1271:             0
        !          1272:             );
        !          1273: 
        !          1274:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !          1275:     } while (rc == FALSE);
        !          1276: 
        !          1277:     //
        !          1278:     // If this is not a ReadIo response than protocol is screwed up.
        !          1279:     // assert that protocol is ok.
        !          1280:     //
        !          1281: 
        !          1282:     st = Reply->ReturnStatus;
        !          1283:     assert(Reply->ApiNumber == DbgKdReadIoSpaceApi);
        !          1284: 
        !          1285:     //
        !          1286:     // Reset message address to reply.
        !          1287:     //
        !          1288: 
        !          1289:     a = &Reply->u.ReadWriteIo;
        !          1290:     st = Reply->ReturnStatus;
        !          1291: 
        !          1292:     switch ( DataSize ) {
        !          1293:         case 1:
        !          1294:             *(PUCHAR)ReturnedData = (UCHAR)a->DataValue;
        !          1295:             break;
        !          1296:         case 2:
        !          1297:             *(PUSHORT)ReturnedData = (USHORT)a->DataValue;
        !          1298:             break;
        !          1299:         case 4:
        !          1300:             *(PULONG)ReturnedData = a->DataValue;
        !          1301:             break;
        !          1302:         }
        !          1303: 
        !          1304:     return st;
        !          1305: }
        !          1306: 
        !          1307: DWORD
        !          1308: DbgKdWriteIoSpace(
        !          1309:     IN PVOID IoAddress,
        !          1310:     IN ULONG DataValue,
        !          1311:     IN ULONG DataSize
        !          1312:     )
        !          1313: 
        !          1314: /*++
        !          1315: 
        !          1316: Routine Description:
        !          1317: 
        !          1318:     This function is used write a byte, short, or long (1,2,4 bytes) to
        !          1319:     the specified I/O address.
        !          1320: 
        !          1321: Arguments:
        !          1322: 
        !          1323:     IoAddress - Supplies the Io address to write to.
        !          1324: 
        !          1325:     DataValue - Supplies the value to write to the I/O address.
        !          1326: 
        !          1327:     DataSize - Supplies the size in bytes to write. Values of 1, 2, or
        !          1328:         4 are accepted.
        !          1329: 
        !          1330: Return Value:
        !          1331: 
        !          1332:     ERROR_SUCCESS - Data was successfully written to the I/O
        !          1333:         address.
        !          1334: 
        !          1335:     ERROR_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
        !          1336:         specified.
        !          1337: 
        !          1338:     !ERROR_SUCCESS - TBD
        !          1339: 
        !          1340: --*/
        !          1341: 
        !          1342: {
        !          1343: 
        !          1344:     DBGKD_MANIPULATE_STATE m;
        !          1345:     PDBGKD_MANIPULATE_STATE Reply;
        !          1346:     PDBGKD_READ_WRITE_IO a = &m.u.ReadWriteIo;
        !          1347:     DWORD st;
        !          1348:     BOOLEAN rc;
        !          1349: 
        !          1350:     switch ( DataSize ) {
        !          1351:         case 1:
        !          1352:         case 2:
        !          1353:         case 4:
        !          1354:             break;
        !          1355:         default:
        !          1356:             return ERROR_INVALID_PARAMETER;
        !          1357:         }
        !          1358: 
        !          1359:     //
        !          1360:     // Format state manipulate message
        !          1361:     //
        !          1362: 
        !          1363:     m.ApiNumber = DbgKdWriteIoSpaceApi;
        !          1364:     m.ReturnStatus = STATUS_PENDING;
        !          1365: 
        !          1366:     a->DataSize = DataSize;
        !          1367:     a->IoAddress = IoAddress;
        !          1368:     a->DataValue = DataValue;
        !          1369: 
        !          1370:     //
        !          1371:     // Send the message and then wait for reply
        !          1372:     //
        !          1373: 
        !          1374:     do {
        !          1375:         DbgKdpWritePacket(
        !          1376:             &m,
        !          1377:             sizeof(m),
        !          1378:             PACKET_TYPE_KD_STATE_MANIPULATE,
        !          1379:             NULL,
        !          1380:             0
        !          1381:             );
        !          1382: 
        !          1383:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !          1384:     } while (rc == FALSE);
        !          1385: 
        !          1386:     //
        !          1387:     // If this is not a WriteIo response than protocol is screwed up.
        !          1388:     // assert that protocol is ok.
        !          1389:     //
        !          1390: 
        !          1391:     st = Reply->ReturnStatus;
        !          1392:     assert(Reply->ApiNumber == DbgKdWriteIoSpaceApi);
        !          1393: 
        !          1394:     //
        !          1395:     // Reset message address to reply.
        !          1396:     //
        !          1397: 
        !          1398:     a = &Reply->u.ReadWriteIo;
        !          1399:     st = Reply->ReturnStatus;
        !          1400: 
        !          1401:     //
        !          1402:     // free the packet
        !          1403:     //
        !          1404: 
        !          1405:     return st;
        !          1406: }
        !          1407: 
        !          1408: 
        !          1409: VOID far
        !          1410: DbgKdpKbdPollThread(VOID)
        !          1411: {
        !          1412:     HANDLE StandardInputHandle;
        !          1413:     DWORD i;
        !          1414:     BOOLEAN rc;
        !          1415:     UCHAR   c;
        !          1416: 
        !          1417:     //
        !          1418:     // Capture all typed input immediately so that control-c,
        !          1419:     // control-break, etc, get processed in a timely fashion.
        !          1420:     // Stuff the characters into an anonymous pipe, from which
        !          1421:     // DbgKdpGetConsole byte will read them.
        !          1422:     //
        !          1423:     // (WHAT??? A PIPE???  Very very simple way to get data flow
        !          1424:     //  between two threads correctly synchronized, folks.)
        !          1425:     //
        !          1426: 
        !          1427:     StandardInputHandle = GetStdHandle(STD_INPUT_HANDLE);
        !          1428: 
        !          1429:     while (TRUE) {
        !          1430:         rc = ReadFile(StandardInputHandle,&c,1,&i,NULL);
        !          1431:         if ((rc != TRUE) || (i != 1)) {
        !          1432:         continue;
        !          1433:         }
        !          1434:         if (c == CONTROL_B) {
        !          1435:             exit(0);
        !          1436:         } else if (c == CONTROL_D) {
        !          1437:             chLastCommand[0] = '\0';
        !          1438:             if (KdDebug) {
        !          1439:                 KdDebug = FALSE;
        !          1440:             } else {
        !          1441:                 KdDebug = TRUE;
        !          1442:             }
        !          1443:             continue;
        !          1444:         } else if (c == CONTROL_R) {
        !          1445:             KdResync = TRUE;
        !          1446:             chLastCommand[0] = '\0';
        !          1447:             continue;
        !          1448:         }
        !          1449:         rc = WriteFile(PipeWrite, &c, 1, &i, NULL);
        !          1450:         if ((rc != TRUE) || (i != 1)) {
        !          1451:             continue;
        !          1452:         }
        !          1453: //        FlushFileBuffers(PipeWrite);
        !          1454:     }
        !          1455: }
        !          1456: 
        !          1457: BOOL
        !          1458: DbgKdpGetConsoleByte(
        !          1459:     PVOID pBuf,
        !          1460:     DWORD cbBuf,
        !          1461:     LPDWORD pcbBytesRead
        !          1462:     )
        !          1463: {
        !          1464:     return ReadFile(PipeRead,pBuf,cbBuf,pcbBytesRead,NULL);
        !          1465: }
        !          1466: 
        !          1467: PUCHAR
        !          1468: DbgKdGets(
        !          1469:     PUCHAR Buffer,
        !          1470:     USHORT Length
        !          1471:     )
        !          1472: {
        !          1473:     DWORD i;
        !          1474:     BOOLEAN rc;
        !          1475:     USHORT j;
        !          1476:     UCHAR   c;
        !          1477: 
        !          1478:     for (j = 0; (j+1) < Length; j++) {
        !          1479: 
        !          1480:         rc = DbgKdpGetConsoleByte(&c, 1, &i);
        !          1481: 
        !          1482:                 if ((rc != TRUE) || (i != 1)) {
        !          1483:         }
        !          1484: 
        !          1485:         if (c == '\n') {
        !          1486:             Buffer[j] = '\n';
        !          1487:             Buffer[j+1] = '\0';
        !          1488:             return Buffer;
        !          1489:         }
        !          1490: 
        !          1491:         Buffer[j] = c;
        !          1492: 
        !          1493:     }
        !          1494:     Buffer[j-1] = '\0';
        !          1495:     return Buffer;
        !          1496: }
        !          1497: 
        !          1498: 
        !          1499: 
        !          1500: DWORD
        !          1501: DbgKdReboot(
        !          1502:     VOID
        !          1503:     )
        !          1504: 
        !          1505: /*++
        !          1506: 
        !          1507: Routine Description:
        !          1508: 
        !          1509:     This function reboots being debugged.
        !          1510: 
        !          1511: Arguments:
        !          1512: 
        !          1513:     None.
        !          1514: 
        !          1515: Return Value:
        !          1516: 
        !          1517:     None.
        !          1518: 
        !          1519: --*/
        !          1520: 
        !          1521: {
        !          1522:     DBGKD_MANIPULATE_STATE m;
        !          1523: 
        !          1524:     //
        !          1525:     // Format state manipulate message
        !          1526:     //
        !          1527: 
        !          1528:     m.ApiNumber = DbgKdRebootApi;
        !          1529:     m.ReturnStatus = STATUS_PENDING;
        !          1530: 
        !          1531:     //
        !          1532:     // Send the message.
        !          1533:     //
        !          1534: 
        !          1535:     DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
        !          1536: 
        !          1537:     return ERROR_SUCCESS;
        !          1538: }
        !          1539: 
        !          1540: 
        !          1541: DWORD
        !          1542: DbgKdReadPhysicalMemory(
        !          1543:     IN PHYSICAL_ADDRESS TargetBaseAddress,
        !          1544:     OUT PVOID UserInterfaceBuffer,
        !          1545:     IN ULONG TransferCount,
        !          1546:     OUT PULONG ActualBytesRead OPTIONAL
        !          1547:     )
        !          1548: 
        !          1549: /*++
        !          1550: 
        !          1551: Routine Description:
        !          1552: 
        !          1553:     This function reads the specified data from the physical memory of
        !          1554:     the system being debugged.
        !          1555: 
        !          1556: Arguments:
        !          1557: 
        !          1558:     TargetBaseAddress - Supplies the physical address of the memory to read
        !          1559:         from the system being debugged.
        !          1560: 
        !          1561:     UserInterfaceBuffer - Supplies the address of the buffer in the user
        !          1562:         interface that data read is to be placed.
        !          1563: 
        !          1564:     TransferCount - Specifies the number of bytes to read.
        !          1565: 
        !          1566:     ActualBytesRead - An optional parameter that if supplied, returns
        !          1567:         the number of bytes actually read.
        !          1568: 
        !          1569: Return Value:
        !          1570: 
        !          1571:     ERROR_SUCCESS - The specified read occured.
        !          1572: 
        !          1573:     ERROR_MORE_DATA - A read that is too large was specified.
        !          1574: 
        !          1575:     ERROR_NO_ACCESS - TBD       // Can you even HAVE an access
        !          1576:                                         // violation with a physical
        !          1577:                                         // memory access??
        !          1578: 
        !          1579:     !ERROR_SUCCESS - TBD
        !          1580: 
        !          1581: --*/
        !          1582: 
        !          1583: {
        !          1584:     DBGKD_MANIPULATE_STATE m;
        !          1585:     PDBGKD_MANIPULATE_STATE Reply;
        !          1586:     PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
        !          1587:     DWORD st;
        !          1588:     BOOLEAN rc;
        !          1589: 
        !          1590:     if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
        !          1591:         return ERROR_MORE_DATA;
        !          1592:         }
        !          1593: 
        !          1594:     //
        !          1595:     // Format state manipulate message
        !          1596:     //
        !          1597: 
        !          1598:     m.ApiNumber = DbgKdReadPhysicalMemoryApi;
        !          1599:     m.ReturnStatus = STATUS_PENDING;
        !          1600:     //
        !          1601:     // BUGBUG TargetBaseAddress should be >32 bits
        !          1602:     //
        !          1603:     a->TargetBaseAddress = (PVOID)TargetBaseAddress.LowPart;
        !          1604:     a->TransferCount = TransferCount;
        !          1605:     a->ActualBytesRead = 0L;
        !          1606: 
        !          1607:     //
        !          1608:     // Send the message and then wait for reply
        !          1609:     //
        !          1610: 
        !          1611:     do {
        !          1612:         DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
        !          1613: 
        !          1614:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !          1615:     } while (rc == FALSE);
        !          1616: 
        !          1617:     //
        !          1618:     // If this is not a ReadMemory response then protocol is screwed up.
        !          1619:     // assert that protocol is ok.
        !          1620:     //
        !          1621: 
        !          1622:     st = Reply->ReturnStatus;
        !          1623:     assert(Reply->ApiNumber == DbgKdReadPhysicalMemoryApi);
        !          1624: 
        !          1625:     //
        !          1626:     // Reset message address to reply.
        !          1627:     //
        !          1628: 
        !          1629:     a = &Reply->u.ReadMemory;
        !          1630:     assert(a->ActualBytesRead <= TransferCount);
        !          1631: 
        !          1632:     //
        !          1633:     // Return actual bytes read, and then transfer the bytes
        !          1634:     //
        !          1635: 
        !          1636:     if (ActualBytesRead) {
        !          1637:         *ActualBytesRead = a->ActualBytesRead;
        !          1638:     }
        !          1639:     st = Reply->ReturnStatus;
        !          1640: 
        !          1641:     //
        !          1642:     // Since read response data follows message, Reply+1 should point
        !          1643:     // at the data
        !          1644:     //
        !          1645: 
        !          1646:     memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead);
        !          1647: 
        !          1648:     return st;
        !          1649: }
        !          1650: 
        !          1651: 
        !          1652: DWORD
        !          1653: DbgKdWritePhysicalMemory(
        !          1654:     IN PHYSICAL_ADDRESS TargetBaseAddress,
        !          1655:     OUT PVOID UserInterfaceBuffer,
        !          1656:     IN ULONG TransferCount,
        !          1657:     OUT PULONG ActualBytesWritten OPTIONAL
        !          1658:     )
        !          1659: 
        !          1660: /*++
        !          1661: 
        !          1662: Routine Description:
        !          1663: 
        !          1664:     This function writes the specified data to the physical memory of the
        !          1665:     system being debugged.
        !          1666: 
        !          1667: Arguments:
        !          1668: 
        !          1669:     TargetBaseAddress - Supplies the physical address of the memory to write
        !          1670:         to the system being debugged.
        !          1671: 
        !          1672:     UserInterfaceBuffer - Supplies the address of the buffer in the user
        !          1673:         interface that contains the data to be written.
        !          1674: 
        !          1675:     TransferCount - Specifies the number of bytes to write.
        !          1676: 
        !          1677:     ActualBytesWritten - An optional parameter that if supplied, returns
        !          1678:         the number of bytes actually written.
        !          1679: 
        !          1680: Return Value:
        !          1681: 
        !          1682:     ERROR_SUCCESS - The specified read occured.
        !          1683: 
        !          1684:     ERROR_MORE_DATA - A read that is to large was specified.
        !          1685: 
        !          1686:     ERROR_NO_ACCESS - TBD       // Can you even HAVE an access
        !          1687:                                         // violation with a physical
        !          1688:                                         // memory access??
        !          1689: 
        !          1690:     !ERROR_SUCCESS - TBD
        !          1691: 
        !          1692: --*/
        !          1693: 
        !          1694: {
        !          1695:     DBGKD_MANIPULATE_STATE m;
        !          1696:     PDBGKD_MANIPULATE_STATE Reply;
        !          1697:     PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
        !          1698:     DWORD st;
        !          1699:     BOOLEAN rc;
        !          1700: 
        !          1701:     if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
        !          1702:         return ERROR_MORE_DATA;
        !          1703:         }
        !          1704: 
        !          1705:     //
        !          1706:     // Format state manipulate message
        !          1707:     //
        !          1708: 
        !          1709:     m.ApiNumber = DbgKdWritePhysicalMemoryApi;
        !          1710:     m.ReturnStatus = STATUS_PENDING;
        !          1711:     //
        !          1712:     // BUGBUG TargetBaseAddress should be >32 bits
        !          1713:     //
        !          1714:     a->TargetBaseAddress = (PVOID)TargetBaseAddress.LowPart;
        !          1715:     a->TransferCount = TransferCount;
        !          1716:     a->ActualBytesWritten = 0L;
        !          1717: 
        !          1718:     //
        !          1719:     // Send the message and data to write and then wait for reply
        !          1720:     //
        !          1721: 
        !          1722:     do {
        !          1723:         DbgKdpWritePacket(
        !          1724:             &m,
        !          1725:             sizeof(m),
        !          1726:             PACKET_TYPE_KD_STATE_MANIPULATE,
        !          1727:             UserInterfaceBuffer,
        !          1728:             (USHORT)TransferCount
        !          1729:             );
        !          1730: 
        !          1731:         rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
        !          1732:     } while (rc == FALSE);
        !          1733: 
        !          1734:     //
        !          1735:     // If this is not a WriteMemory response than protocol is screwed up.
        !          1736:     // assert that protocol is ok.
        !          1737:     //
        !          1738: 
        !          1739:     st = Reply->ReturnStatus;
        !          1740:     assert(Reply->ApiNumber == DbgKdWritePhysicalMemoryApi);
        !          1741: 
        !          1742:     //
        !          1743:     // Reset message address to reply.
        !          1744:     //
        !          1745: 
        !          1746:     a = &Reply->u.WriteMemory;
        !          1747:     assert(a->ActualBytesWritten <= TransferCount);
        !          1748: 
        !          1749:     //
        !          1750:     // Return actual bytes written
        !          1751:     //
        !          1752: 
        !          1753:     if (ActualBytesWritten) {
        !          1754:         *ActualBytesWritten = a->ActualBytesWritten;
        !          1755:     }
        !          1756:     st = Reply->ReturnStatus;
        !          1757: 
        !          1758:     return st;
        !          1759: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.