Advertisement
Guest User

xbdm dmserv.c

a guest
Jun 24th, 2015
1,187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 89.39 KB | None | 0 0
  1.  /*
  2.  Copyright (c) 2013 Nathan LeRoux
  3.  
  4.  Permission is hereby granted, free of charge, to any person obtaining a copy
  5.  of this software and associated documentation files (the "Software"), to deal
  6.  in the Software without restriction, including without limitation the rights
  7.  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8.  copies of the Software, and to permit persons to whom the Software is
  9.  furnished to do so, subject to the following conditions:
  10.  
  11.  The above copyright notice and this permission notice shall be included in
  12.  all copies or substantial portions of the Software.
  13.  
  14.  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15.  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16.  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17.  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18.  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19.  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20.  THE SOFTWARE.
  21.  */
  22.  
  23. #include "dmincludes.h"
  24.  
  25. DMCONN rgdmc[CONNECTION_MAX];
  26. SOCKET sockServ, sockName;
  27.  
  28. const char rgchHex[] = "0123456789ABCDEF";
  29. char *rgszDumpMode[] = { "smart", "enabled", "disabled" };
  30.  
  31. /* BEGIN MICROSOFT CODE */
  32.  
  33. int SgnCompareRgch(const char *sz1, const char *sz2, int cch)
  34. {
  35.     while(cch-- && *sz1) {
  36.         char ch1 = *sz1++;
  37.         char ch2 = *sz2++;
  38.         if(ch1 >= 'a' && ch2 <= 'z')
  39.             ch1 -= 32;
  40.         if(ch2 >= 'a' && ch2 <= 'z')
  41.             ch2 -= 32;
  42.         if(ch1 != ch2)
  43.             return ch1 - ch2;
  44.     }
  45.     if(*sz1)
  46.         return *sz1;
  47.     return cch < 0 ? 0 : -*sz2;
  48. }
  49.  
  50. BOOL FEqualRgch(const char *sz1, const char *sz2, int cch)
  51. {
  52.     return SgnCompareRgch(sz1, sz2, cch) == 0;
  53. }
  54.  
  55. DWORD DwHexFromSz(LPCSTR sz, LPCSTR *szOut)
  56. {
  57.     DWORD dw = 0;
  58.  
  59.     for(;;) {
  60.         if(*sz >= '0' && *sz <= '9')
  61.             dw = dw * 16 + (*sz - '0');
  62.         else if(*sz >= 'A' && *sz <= 'F')
  63.             dw = dw * 16 + (*sz - 'A' + 10);
  64.         else if(*sz >= 'a' && *sz <= 'f')
  65.             dw = dw * 16 + (*sz - 'a' + 10);
  66.         else
  67.             break;
  68.         ++sz;
  69.     }
  70.     if(szOut)
  71.         *szOut = sz;
  72.     return dw;
  73. }
  74.  
  75. DWORD DwFromSz(LPCSTR sz, int *pcchUsed)
  76. {
  77.     DWORD dw = 0;
  78.     LPCSTR szStart = sz;
  79.  
  80.     /* Process decimal, octal, or hex */
  81.     if(*sz == '0') {
  82.         ++sz;
  83.         if(*sz == 'x')
  84.             dw = DwHexFromSz(++sz, &sz);
  85.         else
  86.             while(*sz >= '0' && *sz <= '7')
  87.                 dw = dw * 8 + (*sz++ - '0');
  88.     } else
  89.         while(*sz >= '0' && *sz <= '9')
  90.             dw = dw * 10 + (*sz++ - '0');
  91.     if(pcchUsed)
  92.         *pcchUsed = sz - szStart;
  93.     return dw;
  94. }
  95.  
  96. __inline BOOL FIsSpace(char ch)
  97. {
  98.     return ch == ' ' || ch == '\015' || ch == 0;
  99. }
  100.  
  101. const char *PchGetParam(LPCSTR szCmd, LPCSTR szKey, BOOL fNeedValue)
  102. {
  103.     const char *pchTok;
  104.     int cchTok;
  105.     BOOL fQuote = FALSE;
  106.  
  107.     /* Skip the command */
  108.     for(pchTok = szCmd; !FIsSpace(*pchTok); ++pchTok);
  109.  
  110.     while(*pchTok) {
  111.         /* Skip leading spaces */
  112.         while(*pchTok && FIsSpace(*pchTok))
  113.             ++pchTok;
  114.         if(!*pchTok)
  115.             return NULL;
  116.         for(cchTok = 0; !FIsSpace(pchTok[cchTok]); ++cchTok) {
  117.             if(pchTok[cchTok] == '=') {
  118.                 if(FEqualRgch(szKey, pchTok, cchTok))
  119.                     return pchTok + cchTok + 1; /* Skip the '=' */
  120.                 break;
  121.             }
  122.         }
  123.         /* If we didn't see the '=' we need to check anyway */
  124.         if(!fNeedValue && pchTok[cchTok] != '=' && FEqualRgch(szKey, pchTok,
  125.                 cchTok))
  126.             return pchTok + cchTok;
  127.         /* No match, so we need to skip past the value */
  128.         pchTok += cchTok;
  129.         while(*pchTok && (!FIsSpace(*pchTok) || fQuote))
  130.             if(*pchTok++ == '"')
  131.                 fQuote = !fQuote;
  132.     }
  133.     return NULL;
  134. }
  135.  
  136. void GetParam(LPCSTR szLine, LPSTR szBuf, int cchBuf)
  137. {
  138.     int cch = 0;
  139.     BOOL fQuote = FALSE;
  140.  
  141.     while(cch < cchBuf-1 && *szLine && (!FIsSpace(*szLine) || fQuote)) {
  142.         if(*szLine == '"') {
  143.             if(fQuote && szLine[1] == '"') {
  144.                 /* Double quote inside a string gets copied as a single
  145.                  * quote */
  146.                 szBuf[cch++] = '"';
  147.                 szLine += 2;
  148.             } else {
  149.                 fQuote = !fQuote;
  150.                 ++szLine;
  151.             }
  152.         } else
  153.             szBuf[cch++] = *szLine++;
  154.     }
  155.     szBuf[cch] = 0;
  156. }
  157.  
  158. BOOL FGetSzParam(LPCSTR szLine, LPCSTR szKey, LPSTR szBuf, int cchBuf)
  159. {
  160.     LPCSTR pch = PchGetParam(szLine, szKey, TRUE);
  161.     if(!pch)
  162.         return FALSE;
  163.     GetParam(pch, szBuf, cchBuf);
  164.     return TRUE;
  165. }
  166.  
  167. BOOL FGetDwParam(LPCSTR szLine, LPCSTR szKey, DWORD *pdw)
  168. {
  169.     int cch;
  170.     char sz[32];
  171.     LPCSTR pch = PchGetParam(szLine, szKey, TRUE);
  172.     if(!pch)
  173.         return FALSE;
  174.     GetParam(pch, sz, sizeof sz);
  175.     *pdw = DwFromSz(sz, &cch);
  176.     return FIsSpace(sz[cch]);
  177. }
  178.  
  179. /* END MICROSOFT CODE */
  180.  
  181. BOOL FGetVectorParam(LPCSTR szLine, LPCSTR szKey, float *pvr)
  182. {
  183.     char sz[63];
  184.     int j = 0, i;
  185.  
  186.     LPCSTR pch = PchGetParam(szLine, szKey, TRUE);
  187.     if(!pch)
  188.         return FALSE;
  189.     GetParam(pch, sz, sizeof sz);
  190.    
  191.     for(i = 0;i < 4;i++)
  192.     {
  193.         ((DWORD*)pvr)[i] = DwFromSz(sz + j, NULL);
  194.  
  195.         do{ j++; } while(sz[j] != ',');
  196.  
  197.         if(i < 3 && (sz[j] != ',') && !FIsSpace(sz[j]))
  198.             return FALSE;
  199.  
  200.         j++;
  201.     }
  202.  
  203.     return TRUE;
  204. }
  205.  
  206. BOOL FGetQwordParam(LPCSTR szLine, LPCSTR szKey, ULARGE_INTEGER *plu)
  207. {
  208.     int cch;
  209.     char sz[32];
  210.     LPCSTR pch;
  211.  
  212.     pch = PchGetParam(szLine, szKey, TRUE);
  213.     if(!pch)
  214.         return FALSE;
  215.     GetParam(pch, sz, sizeof sz - 1);
  216.     sz[sizeof sz - 1] = 0;
  217.  
  218.     /* Verify the 0q prefix */
  219.     if(sz[0] != '0' || sz[1] != 'q')
  220.         return FALSE;
  221.     /* Make sure we have a bunch of hex characters */
  222.     for(cch = 2; cch < sizeof sz && !FIsSpace(sz[cch]); ++cch) {
  223.         if(!(sz[cch] >= '0' && sz[cch] <= '9' ||
  224.                 sz[cch] >= 'A' && sz[cch] <= 'F' ||
  225.                 sz[cch] >= 'a' && sz[cch] <= 'f'))
  226.             return FALSE;
  227.     }
  228.     cch -= 2;
  229.     if(cch <= 0)
  230.         return FALSE;
  231.  
  232.     /* Move the text out to the end of the string and fill the preceding
  233.      * characters with zeroes */
  234.     memmove(&sz[sizeof sz - 1 - cch], &sz[2], cch);
  235.     memset(sz, '0', sizeof sz - 1 - cch);
  236.  
  237.     /* Now parse out the two dwords */
  238.     plu->LowPart = DwHexFromSz(&sz[sizeof sz - 9], NULL);
  239.     sz[sizeof sz - 9] = 0;
  240.     plu->HighPart = DwHexFromSz(&sz[sizeof sz - 17], NULL);
  241.     return TRUE;
  242. }
  243.  
  244. BOOL FGetNamedDwParam(LPCSTR szLine, LPCSTR szKey, DWORD *pdw, LPSTR szResp)
  245. {
  246.     if(!FGetDwParam(szLine, szKey, pdw)) {
  247.         RtlSprintf(szResp, "missing %s", szKey);
  248.         return FALSE;
  249.     }
  250.     return TRUE;
  251. }
  252.  
  253. ULONG UlAddrFromSz(LPCSTR sz)
  254. {
  255.     ULONG ul;
  256.     int ib;
  257.     int ich;
  258.  
  259.     for(ib = 0; ib < 4; ++ib) {
  260.         BYTE b = 0;
  261.  
  262.         for(ich = 0; ich < 3; ++ich) {
  263.             if(sz[ich] < '0' || sz[ich] > '9')
  264.                 break;
  265.             b = 10 * b + (sz[ich] - '0');
  266.         }
  267.         if(ich == 0 || sz[ich] != (ib == 3 ? 0 : '.'))
  268.             return 0;
  269.         sz += ich + 1;
  270.         ((BYTE *)&ul)[ib ^ 3] = b;
  271.     }
  272.     return ul;
  273. }
  274.  
  275. void GetFileAttrSz(LPSTR sz, ULONG dwAttributes, PLARGE_INTEGER pliChange,
  276.     PLARGE_INTEGER pliCreate, PLARGE_INTEGER pliSize)
  277. {
  278.     RtlSprintf(sz, "sizehi=0x%x sizelo=0x%x createhi=0x%08x createlo=0x%08x "
  279.         "changehi=0x%08x changelo=0x%08x%s%s%s", pliSize->HighPart,
  280.         pliSize->LowPart, pliCreate->HighPart, pliCreate->LowPart,
  281.         pliChange->HighPart, pliChange->LowPart,
  282.         dwAttributes & FILE_ATTRIBUTE_DIRECTORY ? " directory" : "",
  283.         dwAttributes & FILE_ATTRIBUTE_READONLY ? " readonly" : "",
  284.         dwAttributes & FILE_ATTRIBUTE_HIDDEN ? " hidden" : "");
  285. }
  286.  
  287. VOID FStopServ()
  288. {
  289.     int i;
  290.  
  291.     closesocket(sockServ);
  292.     closesocket(sockName);
  293.  
  294.     for(i = 0;i < CONNECTION_MAX;i++)
  295.         if(rgdmc[i].bActive)
  296.             closesocket(rgdmc[i].s);
  297. }
  298.  
  299. int FSend(SOCKET s, LPCSTR fmt, ...)
  300. {
  301.     char buf[0x200];
  302.  
  303.     va_list list;
  304.     va_start(list, fmt);
  305.     RtlVsnprintf(buf, sizeof(buf), fmt, list);
  306.     va_end(list);
  307.  
  308.     return send(s, buf, strlen(buf), 0);
  309. }
  310.  
  311. int FSendLine(SOCKET s, LPCSTR fmt, ...)
  312. {
  313.     char buf[0x202];
  314.     int i;
  315.  
  316.     va_list list;
  317.     va_start(list, fmt);
  318.     i = RtlVsnprintf(buf, sizeof(buf) - 2, fmt, list);
  319.     va_end(list);
  320.  
  321.     strcat(buf, "\r\n");
  322.  
  323.     return send(s, buf, i + 2, 0);
  324. }
  325.  
  326. LPCSTR SzStdResponse(HRESULT hr)
  327. {
  328.     LPCSTR pszResp;
  329.  
  330.     switch(hr) {
  331.     case XBDM_LINE_TOO_LONG:
  332.         pszResp = "line too long";
  333.         break;
  334.     case XBDM_NOSUCHFILE:
  335.         pszResp = "file not found";
  336.         break;
  337.     case XBDM_NOMODULE:
  338.         pszResp = "no such module";
  339.         break;
  340.     case XBDM_MEMUNMAPPED:
  341.         pszResp = "memory not mapped";
  342.         break;
  343.     case XBDM_NOTHREAD:
  344.         pszResp = "no such thread";
  345.         break;
  346.     case XBDM_INVALIDCMD:
  347.         pszResp = "unknown command";
  348.         break;
  349.     case XBDM_NOTSTOPPED:
  350.         pszResp = "not stopped";
  351.         break;
  352.     case XBDM_ALREADYSTOPPED:
  353.         pszResp = "already stopped";
  354.         break;
  355.     case XBDM_MUSTCOPY:
  356.         pszResp = "file must be copied";
  357.         break;
  358.     case XBDM_ALREADYEXISTS:
  359.         pszResp = "file already exists";
  360.         break;
  361.     case XBDM_DIRNOTEMPTY:
  362.         pszResp = "directory not empty";
  363.         break;
  364.     case XBDM_BADFILENAME:
  365.         pszResp = "filename is invalid";
  366.         break;
  367.     case XBDM_CANNOTCREATE:
  368.         pszResp = "file cannot be created";
  369.         break;
  370.     case XBDM_DEVICEFULL:
  371.         pszResp = "no room on device";
  372.         break;
  373.     case XBDM_MULTIRESPONSE:
  374.         pszResp = "multiline response follows";
  375.         break;
  376.     case XBDM_BINRESPONSE:
  377.         pszResp = "binary response follows";
  378.         break;
  379.     case XBDM_READYFORBIN:
  380.         pszResp = "send binary data";
  381.         break;
  382.     case XBDM_CANNOTACCESS:
  383.         pszResp = "access denied";
  384.         break;
  385.     case XBDM_NOTDEBUGGABLE:
  386.         pszResp = "not debuggable";
  387.         break;
  388.     case XBDM_BADCOUNTTYPE:
  389.         pszResp = "type invalid";
  390.         break;
  391.     case XBDM_COUNTUNAVAILABLE:
  392.         pszResp = "data not available";
  393.         break;
  394.     case XBDM_NOTLOCKED:
  395.         pszResp = "box is not locked";
  396.         break;
  397.     case XBDM_KEYXCHG:
  398.         pszResp = "key exchange required";
  399.         break;
  400.     case XBDM_MUSTBEDEDICATED:
  401.         pszResp = "dedicated connection required";
  402.         break;
  403.     case E_OUTOFMEMORY:
  404.         pszResp = "out of memory";
  405.         break;
  406.     case E_UNEXPECTED:
  407.         pszResp = "unexpected error";
  408.         break;
  409.     case E_INVALIDARG:
  410.         pszResp = "bad parameter";
  411.         break;
  412.     case XBDM_NOERR:
  413.         pszResp = "OK";
  414.         break;
  415.     default:
  416.         pszResp = "";
  417.         break;
  418.     }
  419.     return pszResp;
  420. }
  421.  
  422. int SendHrSzResp(SOCKET s, HRESULT hr, LPCSTR szResp, LPSTR szBuf)
  423. {
  424.     /* Make sure we have an error code we like */
  425.     if(((hr >> 16) & 0x7fff) != FACILITY_XBDM) {
  426.         hr = SUCCEEDED(hr) ? XBDM_NOERR : XBDM_UNDEFINED;
  427.         if(!szResp)
  428.             szResp = SzStdResponse(E_UNEXPECTED);
  429.     } else if((hr & 0xffff) > 0xff)
  430.         hr = XBDM_UNDEFINED;
  431.  
  432.     if(FAILED(hr))
  433.         szBuf[0] = '4';
  434.     else
  435.         szBuf[0] = '2';
  436.     szBuf[1] = (char) ('0' + (hr & 0xffff) / 10);   // overflow?
  437.     szBuf[2] = (char) ('0' + (hr & 0xffff) % 10);
  438.     szBuf[3] = '-';
  439.     szBuf[4] = ' ';
  440.     if(szResp != szBuf) {
  441.         if(szResp)
  442.             strcpy(szBuf + 5, szResp);
  443.         else
  444.             szBuf[5] = 0;
  445.     }
  446.     return FSendLine(s, "%s", szBuf);
  447. }
  448.  
  449. VOID DoReadWrite(PDMCONN pdmc, BOOL bCanRead)
  450. {
  451.     int i, j;
  452.     DWORD dw;
  453.     char sz[0x200];
  454.     char resp[0x200];
  455.     HRESULT hr;
  456.  
  457.     if(!pdmc->bConversation)
  458.     {
  459.         // We are not currently in a handling function
  460.  
  461.         // Check for shutdown
  462.         if(pdmc->bShutdown)
  463.         {
  464.             if(!pdmc->bKeepAlive)
  465.                 closesocket(pdmc->s);
  466.  
  467.             ZeroMemory(pdmc, sizeof(DMCONN));
  468.  
  469.             return;
  470.         }
  471.  
  472.         // First, scan the buffer to search for newlines
  473.         for(dw = 0;dw < pdmc->dwRecv && (pdmc->szRecv[dw] != '\n');dw++);
  474.  
  475.         // If i == pdmc->dwRecv then there are no commands in the buffer
  476.         if(dw == pdmc->dwRecv)
  477.         {
  478.             // Recieve into the buffer
  479.             if(bCanRead)
  480.             {
  481.                 i = recv(pdmc->s, (char*)pdmc->szRecv + pdmc->dwRecv, sizeof(pdmc->szRecv) - pdmc->dwRecv, 0);
  482.                 if(i <= 0)
  483.                 {
  484.                     pdmc->bShutdown = TRUE;
  485.                     return;
  486.                 }
  487.  
  488.                 pdmc->dwRecv += i;
  489.             }
  490.         }
  491.  
  492.         // Scan the buffer for a newline
  493.         for(dw = 0;dw < pdmc->dwRecv && (pdmc->szRecv[dw] != '\n');dw++);
  494.  
  495.         if(dw != pdmc->dwRecv)
  496.         {
  497.             // We found a command
  498.             if(pdmc->bTooLong)
  499.             {
  500.                 SendHrSzResp(pdmc->s, XBDM_LINE_TOO_LONG, "", sz);
  501.                 pdmc->bTooLong = FALSE;
  502.                 pdmc->dwRecv = 0;
  503.  
  504.                 return;
  505.             }
  506.  
  507.             // Find the command name
  508.             for(i = 0;(pdmc->szRecv[i]) && (pdmc->szRecv[i] != '\r') && (pdmc->szRecv[i] != '\n') && (pdmc->szRecv[i] != ' ');i++)
  509.                 sz[i] = pdmc->szRecv[i];
  510.             sz[i] = 0;
  511.  
  512.             // Now we just walk the list with our super inefficient algo of BRUTE FORCE SEARCHING
  513.             for(j = 0;j < cchcmd && stricmp(sz, rgbcmd[j].szName);j++);
  514.  
  515.             if(j == cchcmd) // Command not found
  516.             {
  517.                 SendHrSzResp(pdmc->s, XBDM_INVALIDCMD, SzStdResponse(XBDM_INVALIDCMD), sz);
  518.  
  519.                 memcpy(sz, pdmc->szRecv, dw - 1);
  520.                 sz[dw - 1] = 0;
  521.  
  522.                 DbgPrint("[xbdm] unknown command \"%s\"\n", sz);
  523.             }
  524.             else if((rgbcmd[j].dwPriv & pdmc->dwPriv) != rgbcmd[j].dwPriv)
  525.             {
  526.                 // Not enough permissions
  527.                 SendHrSzResp(pdmc->s, XBDM_CANNOTACCESS, SzStdResponse(XBDM_CANNOTACCESS), sz);
  528.             }
  529.             else
  530.             {
  531.                 // Command foundzorz
  532.  
  533.                 // Copy the whole string over
  534.                 for(i = 0;(pdmc->szRecv[i] != '\r') && (pdmc->szRecv[i] != '\n');i++)
  535.                     sz[i] = pdmc->szRecv[i];
  536.                
  537.                 sz[i] = 0;
  538.                 resp[0] = 0;
  539.  
  540.                 // Setup some final state information
  541.                 pdmc->dmcc.Buffer = NULL;
  542.                 pdmc->dmcc.BufferSize = 0;
  543.                 pdmc->dmcc.BytesRemaining = 0;
  544.                 pdmc->dmcc.CustomData = &pdmc->dmcd;
  545.                 pdmc->dmcc.DataSize = -1;
  546.                 pdmc->dmcc.HandlingFunction = NULL;
  547.  
  548.                 pdmc->hr = hr = rgbcmd[j].pdmcp(sz, resp, sizeof(resp), &pdmc->dmcc);
  549.  
  550.                 if(hr == XBDM_MULTIRESPONSE
  551.                     || hr == XBDM_BINRESPONSE
  552.                     || hr == XBDM_READYFORBIN)
  553.                     pdmc->bConversation = TRUE;
  554.  
  555.                 if(!pdmc->bKeepAlive)
  556.                 {
  557.                     if(resp[0])
  558.                     {
  559.                         if(SendHrSzResp(pdmc->s, hr, resp, sz) <= 0)
  560.                             pdmc->bShutdown = TRUE;
  561.                     }
  562.                     else if(SendHrSzResp(pdmc->s, hr, SzStdResponse(hr), sz) <= 0)
  563.                         pdmc->bShutdown = TRUE;
  564.                 }
  565.             }
  566.  
  567.             // Fetch the index of the \n
  568.             for(i = 0;pdmc->szRecv[i] != '\n';i++);
  569.  
  570.             // Move the memory
  571.             memmove(pdmc->szRecv, pdmc->szRecv + (i + 1), sizeof(pdmc->szRecv) - (i + 1));
  572.  
  573.             // Adjust the vars
  574.             pdmc->dwRecv -= i + 1;
  575.         }
  576.         else if(pdmc->dwRecv == sizeof(pdmc->szRecv))
  577.             pdmc->bTooLong = TRUE; // Overflow....
  578.  
  579.         // On overflow, just ignore the rest of the data until newline
  580.         if(pdmc->bTooLong)
  581.             pdmc->dwRecv = 0;
  582.     }
  583.     else
  584.     {
  585.         // We are currently in a handling function
  586.  
  587.         ASSERT(pdmc->dmcc.HandlingFunction);
  588.  
  589.         if(pdmc->dmcc.Buffer == NULL)
  590.         {
  591.             pdmc->dmcc.Buffer = pdmc->szBuf;
  592.             pdmc->dmcc.BufferSize = sizeof(pdmc->szBuf);
  593.         }
  594.  
  595.         // Check for shutdown
  596.         if(pdmc->bShutdown)
  597.         {
  598.             if(pdmc->hr == XBDM_READYFORBIN)
  599.             {
  600.                 // Multiline responses are free to continue, but they wont go anywhere
  601.                 pdmc->dmcc.DataSize = 0;
  602.                 pdmc->bConversation = FALSE;
  603.             }
  604.         }
  605.  
  606.         if(pdmc->hr == XBDM_READYFORBIN)
  607.         {
  608.             if(bCanRead)
  609.             {
  610.                 if(!pdmc->bShutdown)
  611.                 {
  612.                     i = recv(pdmc->s, (char*)pdmc->dmcc.Buffer,
  613.                         pdmc->dmcc.BytesRemaining > pdmc->dmcc.BufferSize ? pdmc->dmcc.BufferSize : pdmc->dmcc.BytesRemaining,
  614.                         0);
  615.  
  616.                     if(i <= 0)
  617.                     {
  618.                         pdmc->dmcc.DataSize = 0;
  619.                         pdmc->bShutdown = TRUE;
  620.                     }
  621.                     else
  622.                         pdmc->dmcc.DataSize = i;
  623.                 }
  624.  
  625.                 hr = pdmc->dmcc.HandlingFunction(&pdmc->dmcc, resp, sizeof(resp));
  626.  
  627.                 if(!pdmc->bShutdown)
  628.                 {
  629.                     if(pdmc->dmcc.BytesRemaining == 0)
  630.                     {
  631.                         if(hr == XBDM_MULTIRESPONSE
  632.                         || hr == XBDM_BINRESPONSE
  633.                         || hr == XBDM_READYFORBIN)
  634.                         {
  635.                             pdmc->hr = hr;
  636.                             pdmc->bConversation = TRUE;
  637.                             pdmc->dmcc.DataSize = 0;
  638.                         }
  639.                         else
  640.                         {
  641.                             pdmc->bConversation = FALSE;
  642.                             pdmc->dmcc.HandlingFunction = NULL;
  643.                         }
  644.  
  645.                         SendHrSzResp(pdmc->s, hr, SzStdResponse(hr), sz);
  646.                     }
  647.                 }
  648.  
  649.                 if(pdmc->bShutdown)
  650.                     pdmc->bConversation = FALSE;
  651.             }
  652.         }
  653.         else
  654.         {
  655.             if(pdmc->bShutdown || pdmc->dmcc.DataSize == 0 || pdmc->dmcc.DataSize == -1)
  656.             {
  657.                 // Multiline/binary
  658.                 pdmc->dmcc.DataSize = -1;
  659. #ifdef _DEBUG
  660.                 hr = pdmc->dmcc.HandlingFunction(&pdmc->dmcc, NULL, 0x100); // This way i can catch those annoying errors
  661. #else
  662.                 hr = pdmc->dmcc.HandlingFunction(&pdmc->dmcc, NULL, 0);
  663. #endif
  664.  
  665.                 pdmc->Buffer = pdmc->dmcc.Buffer;
  666.             }
  667.  
  668.             if(pdmc->bShutdown)
  669.             {
  670.                 if(FAILED(hr)
  671.                     || hr == XBDM_MULTIRESPONSE
  672.                     || hr == XBDM_BINRESPONSE
  673.                     || hr == XBDM_READYFORBIN) // Just let them keep talking
  674.                     pdmc->bConversation = FALSE;
  675.             }
  676.             else
  677.             {
  678.                 if(hr == XBDM_ENDOFLIST
  679.                         || hr == XBDM_MULTIRESPONSE
  680.                         || hr == XBDM_BINRESPONSE
  681.                         || hr == XBDM_READYFORBIN)
  682.                 {
  683.                     if(pdmc->hr == XBDM_MULTIRESPONSE)
  684.                         FSend(pdmc->s, ".\r\n");
  685.  
  686.                     pdmc->bConversation = FALSE;
  687.  
  688.                     if(hr == XBDM_MULTIRESPONSE
  689.                         || hr == XBDM_BINRESPONSE
  690.                         || hr == XBDM_READYFORBIN)
  691.                     {
  692.                         pdmc->hr = hr;
  693.                         pdmc->bConversation = TRUE;
  694.                     }
  695.                     else
  696.                         pdmc->dmcc.HandlingFunction = NULL;
  697.                 }
  698.                 else if(NT_SUCCESS(hr))
  699.                 {
  700.                     if(pdmc->dmcc.DataSize == -1)
  701.                     {
  702.                         // Null terminated string with a newline
  703.                         if(FSend(pdmc->s, "%s\r\n", pdmc->dmcc.Buffer) <= 0)
  704.                             pdmc->bShutdown = TRUE;
  705.                     }
  706.                     else if(pdmc->dmcc.DataSize != 0)
  707.                     {
  708.                         // Binary data
  709.                         if((i = send(pdmc->s, (char*)pdmc->Buffer, pdmc->dmcc.DataSize, 0)) <= 0)
  710.                             pdmc->bShutdown = TRUE;
  711.  
  712.                         pdmc->dmcc.DataSize -= i;
  713.                         pdmc->Buffer = (PVOID)((DWORD)pdmc->Buffer + i);
  714.                     }
  715.                 }
  716.                 else
  717.                 {
  718.                     if(pdmc->dmcc.DataSize == -1)
  719.                         FSend(pdmc->s, "%s\r\n", pdmc->dmcc.Buffer);
  720.  
  721.                     // Forcefully terminate the connection
  722.                     pdmc->bShutdown = TRUE;
  723.                     pdmc->bConversation = FALSE;
  724.                 }
  725.             }
  726.         }
  727.     }
  728. }
  729.  
  730. VOID AnswerName(SOCKET s)
  731. {
  732.     struct {
  733.         BYTE bRequest;
  734.         BYTE cchName;
  735.         char szName[256];
  736.     } nm;
  737.  
  738.     SOCKADDR_IN sin;
  739.     int cbAddr = sizeof(sin);
  740.     int cbPkt;
  741.  
  742.     cbPkt = recvfrom(s, (char*)&nm, sizeof(nm), 0, (SOCKADDR*)&sin, &cbAddr);
  743.     switch(nm.bRequest)
  744.     {
  745.     case 1:
  746.     case 3:
  747.         if(nm.bRequest == 1)
  748.         {
  749.             nm.bRequest = 0;
  750.  
  751.             if(cbPkt < 2 || cbPkt < (2 + nm.cchName))
  752.                 break;
  753.  
  754.             if(!nm.cchName || strcmpi(nm.szName, g_dmGlobals.rgchDbgName))
  755.                 break;
  756.         }
  757.  
  758.         nm.bRequest = 2;
  759.         break;
  760.     default:
  761.         nm.bRequest = 0;
  762.         break;
  763.     }
  764.  
  765.     if(nm.bRequest)
  766.         sendto(s, (char*)&nm, cbPkt, 0, (SOCKADDR*)&sin, cbAddr);
  767. }
  768.  
  769. ULONG __stdcall ServerThread(LPVOID lpParam)
  770. {
  771.     SOCKET sock;
  772.     BOOL bReuse;
  773.     SOCKADDR_IN sin;
  774.     FD_SET readfds, writefds;
  775.     struct timeval timeout;
  776.     XNADDR xna;
  777.     DMTD *pdmtd;
  778.     int i;
  779.  
  780.     KeSetBasePriorityThread(PsGetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  781.     pdmtd = DmGetCurrentDmtd();
  782.  
  783.     pdmtd->DebugFlags |= DMFLAG_DEBUGTHREAD;
  784.  
  785.     VSetThreadName(-1, "Debugger Command Thread");
  786.  
  787.     ZeroMemory(rgdmc, sizeof(rgdmc));
  788.  
  789.     do
  790.     {
  791.         // Well, this IS the server thread, so if we can't start a server then screw you
  792.         Sleep(5000);
  793.         sockServ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  794.     } while(sockServ == INVALID_SOCKET);
  795.  
  796.     bReuse = TRUE;
  797.     if(setsockopt(sockServ, SOL_SOCKET, SO_DECRYPTSOCK, (char*)&bReuse, sizeof(bReuse)))
  798.     {
  799.         DbgPrint("[xbdm] failed %i\n", WSAGetLastError());
  800.         DebugBreak();
  801.     }
  802.     if(setsockopt(sockServ, SOL_SOCKET, SO_REUSEADDR, (char*)&bReuse, sizeof(bReuse)))
  803.     {
  804.         DbgPrint("[xbdm] failed %i\n", WSAGetLastError());
  805.         DebugBreak();
  806.     }
  807.  
  808.     sin.sin_family = AF_INET;
  809.     sin.sin_port = 730;
  810.     sin.sin_addr.s_addr = INADDR_ANY;
  811.     if(bind(sockServ, (SOCKADDR*)&sin, sizeof(sin))
  812.         || listen(sockServ, 8))
  813.     {
  814.         DbgPrint("[xbdm] failed %i\n", WSAGetLastError());
  815.         DebugBreak();
  816.         goto abortsocket;
  817.     }
  818.  
  819.     sockName = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  820.     if(setsockopt(sockName, SOL_SOCKET, SO_DECRYPTSOCK, (char*)&bReuse, sizeof(bReuse)))
  821.     {
  822.         DbgPrint("[xbdm] failed %i\n", WSAGetLastError());
  823.         DebugBreak();
  824.     }
  825.     if(setsockopt(sockName, SOL_SOCKET, SO_REUSEADDR, (char*)&bReuse, sizeof(bReuse)))
  826.     {
  827.         DbgPrint("[xbdm] failed %i\n", WSAGetLastError());
  828.         DebugBreak();
  829.     }
  830.     if(setsockopt(sockName, SOL_SOCKET, SO_BROADCAST, (char*)&bReuse, sizeof(bReuse)))
  831.     {
  832.         DbgPrint("[xbdm] failed %i\n", WSAGetLastError());
  833.         DebugBreak();
  834.     }
  835.     if(bind(sockName, (SOCKADDR*)&sin, sizeof(sin)))
  836.     {
  837.         DbgPrint("[xbdm] failed %i\n", WSAGetLastError());
  838.         DebugBreak();
  839.     }
  840.  
  841.     DbgPrint("[xbdm] server started\n");
  842.  
  843.     for(;;)
  844.     {
  845.         readfds.fd_count = 0;
  846.         writefds.fd_count = 0;
  847.  
  848.         FD_SET(sockServ, &readfds);
  849.         FD_SET(sockName, &readfds);
  850.  
  851.         for(i = 0;i < CONNECTION_MAX;i++)
  852.         {
  853.             if(rgdmc[i].bActive)
  854.                 FD_SET(rgdmc[i].s, &readfds);
  855.         }
  856.  
  857.         timeout.tv_sec = 0;
  858.         timeout.tv_usec = 0;
  859.  
  860.         if(g_dmGlobals.bDirty)
  861.         {
  862.             FWriteGlobals();
  863.  
  864.             g_dmGlobals.bDirty = FALSE;
  865.         }
  866.  
  867.         if(!g_dmGlobals.bHasIp)
  868.         {
  869.             i = XNetGetTitleXnAddr(&xna);
  870.             if(i != XNET_GET_XNADDR_PENDING)
  871.             {
  872.                 DbgPrint("[xbdm] IP Address Acquired [%i.%i.%i.%i] (0x%08x)\n",
  873.                     xna.ina.S_un.S_un_b.s_b1, xna.ina.S_un.S_un_b.s_b2,
  874.                     xna.ina.S_un.S_un_b.s_b3, xna.ina.S_un.S_un_b.s_b4,
  875.                     i);
  876.  
  877.                 g_dmGlobals.bHasIp = TRUE;
  878.             }
  879.         }
  880.  
  881.         // Yield to others (its the right thing to do)
  882.         Sleep(0);
  883.  
  884.         ProcessQueuedNotifications();
  885.  
  886.         select(0, &readfds, &writefds, NULL, &timeout);
  887.  
  888.         if(FD_ISSET(sockName, &readfds))
  889.             AnswerName(sockName);
  890.  
  891.         if(FD_ISSET(sockServ, &readfds))
  892.         {
  893.             i = sizeof(sin);
  894.             sock = accept(sockServ, (SOCKADDR*)&sin, &i);
  895.  
  896.             for(i = 0;i < CONNECTION_MAX;i++)
  897.             {
  898.                 if(!rgdmc[i].bActive)
  899.                 {
  900.                     rgdmc[i].bActive = TRUE;
  901.                     rgdmc[i].s = sock;
  902.                     memcpy(&rgdmc[i].sin, &sin, sizeof(sin));
  903.                     break;
  904.                 }
  905.             }
  906.  
  907.             if(i == CONNECTION_MAX)
  908.             {
  909.                 // No more connection slots
  910.                 FSendLine(sock, "401- max number of connections exceeded");
  911.                 closesocket(sock);
  912.             }
  913.             else
  914.             {
  915.                 // Some quick init
  916.  
  917.                 // Give all permssions, as we dont have locking yet
  918.                 rgdmc[i].dwPriv = DMPL_PRIV_READ | DMPL_PRIV_WRITE | DMPL_PRIV_CONFIGURE | DMPL_PRIV_CONTROL;
  919.                
  920.                 // Only give hypervisor access if its enabled
  921.                 if(g_dmGlobals.bHypervisorEnabled)
  922.                     rgdmc[i].dwPriv |= DMPL_PRIV_HVX_MASK;
  923.  
  924.                 // Say hello!
  925.                 FSendLine(rgdmc[i].s, "201- connected");
  926.             }
  927.         }
  928.  
  929.         for(i = 0;i < CONNECTION_MAX;i++)
  930.         {
  931.             if(rgdmc[i].bActive)
  932.                 DoReadWrite(&rgdmc[i], FD_ISSET(rgdmc[i].s, &readfds));
  933.         }
  934.     }
  935.  
  936. abortsocket:
  937.     closesocket(sockServ);
  938.  
  939.     DebugBreak();
  940.     return 0;
  941. }
  942.  
  943. DMHRAPI HrGetAltAddr(LPCSTR szCommand, LPSTR szResponse,
  944.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  945. {
  946.     XNADDR xna;
  947.     DWORD dw;
  948.  
  949.     if(!pdmcc)
  950.         return E_FAIL;
  951.  
  952.     dw = XNetGetTitleXnAddr(&xna);
  953.  
  954.     if(dw == XNET_GET_XNADDR_PENDING || dw == XNET_GET_XNADDR_NONE)
  955.         return E_FAIL;
  956.  
  957.     RtlSnprintf(szResponse, cchResponse, "addr=0x%08x", xna.ina.s_addr);
  958.  
  959.     return XBDM_NOERR;
  960. }
  961.  
  962. DMHRAPI HrEndConversation(LPCSTR szCommand, LPSTR szResponse,
  963.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  964. {
  965.     PDMCONN pdmc;
  966.  
  967.     if(!pdmcc)
  968.         return E_FAIL;
  969.  
  970.     // Snag the structure
  971.     pdmc = CONTAINING_RECORD(pdmcc, DMCONN, dmcc);
  972.  
  973.     // Say goodbye
  974.     strcpy(szResponse, "bye");
  975.  
  976.     // Signal shutdown
  977.     pdmc->bShutdown = TRUE;
  978.  
  979.     return XBDM_NOERR;
  980. }
  981.  
  982. DMHRAPI HrMagicReboot(LPCSTR szCommand, LPSTR szResponse,
  983.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  984. {
  985.     PDMCONN pdmc;
  986.  
  987.     char szTmp[MAX_PATH];
  988.     char szLaunchPath[MAX_PATH];
  989.     char szMountPath[MAX_PATH];
  990.     char szCmdLine[MAX_PATH];
  991.  
  992.     DWORD dwMask = 0;
  993.     HRESULT hr = XBDM_NOERR;
  994.  
  995.     szCmdLine[0] = 0;
  996.     szMountPath[0] = 0;
  997.     szLaunchPath[0] = 0;
  998.  
  999.     if(PchGetParam(szCommand, "wait", FALSE))
  1000.         dwMask = DMBOOT_WAIT;
  1001.     else if(PchGetParam(szCommand, "stop", FALSE))
  1002.         dwMask = DMBOOT_STOP;
  1003.     if(PchGetParam(szCommand, "cold", FALSE))
  1004.         dwMask |= DMBOOT_COLD;
  1005.  
  1006.     // TODO: if(stopped and exception) flag |= cold
  1007.     if(FGetSzParam(szCommand, "title", szTmp, sizeof(szTmp)))
  1008.     {
  1009.         if(szTmp[0] == '\\')
  1010.             strcpy_s(szLaunchPath, sizeof(szLaunchPath), szTmp);
  1011.         else if(FAILED(FFileNameToObName(szTmp, szLaunchPath, sizeof(szLaunchPath))))
  1012.             hr = XBDM_NOSUCHFILE;
  1013.     }
  1014.     if(FGetSzParam(szCommand, "directory", szTmp, sizeof(szTmp)))
  1015.     {
  1016.         if(szTmp[0] == '\\')
  1017.             strcpy_s(szMountPath, sizeof(szMountPath), szTmp);
  1018.         else if(FAILED(FFileNameToObName(szTmp, szMountPath, sizeof(szMountPath))))
  1019.             hr = XBDM_NOSUCHFILE;
  1020.     }
  1021.  
  1022.     FGetSzParam(szCommand, "cmdline", szCmdLine, sizeof(szCmdLine));
  1023.  
  1024.     if(NT_SUCCESS(hr))
  1025.     {
  1026.         if(dwMask & DMBOOT_COLD)
  1027.         {
  1028.             pdmc = CONTAINING_RECORD(pdmcc, DMCONN, dmcc);
  1029.             FSendLine(pdmc->s, "200- OK");
  1030.  
  1031.             Sleep(200);
  1032.             FStopServ();
  1033.         }
  1034.  
  1035.         DmRebootEx(dwMask, szLaunchPath, szMountPath, szCmdLine);
  1036.     }
  1037.  
  1038.     return XBDM_NOERR;
  1039. }
  1040.  
  1041. DMHRAPI HrGetConsoleFeatures(LPCSTR szCommand, LPSTR szResponse,
  1042.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1043. {
  1044.     if(!pdmcc)
  1045.         return E_FAIL;
  1046.  
  1047.     strcpy_s(szResponse, cchResponse, "DEBUGGING");
  1048.  
  1049.     if(g_dmGlobals.dwConsoleColor & CONSOLE_COLOR_FLAG_BLUE)
  1050.         strcat_s(szResponse, cchResponse, " 1GB_RAM");
  1051.  
  1052.     return XBDM_NOERR;
  1053. }
  1054.  
  1055. DMHRAPI HrGetConsoleType(LPCSTR szCommand, LPSTR szResponse,
  1056.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1057. {
  1058.     if(!pdmcc)
  1059.         return E_FAIL;
  1060.  
  1061.     if(g_dmGlobals.dwConsoleColor & CONSOLE_COLOR_FLAG_BLACK)
  1062.         strcpy_s(szResponse, cchResponse, "devkit");
  1063.     else if(g_dmGlobals.dwConsoleColor & CONSOLE_COLOR_FLAG_WHITE)
  1064.         strcpy_s(szResponse, cchResponse, "testkit");
  1065.     else
  1066.         strcpy_s(szResponse, cchResponse, "reviewerkit");
  1067.        
  1068.  
  1069.     return XBDM_NOERR;
  1070. }
  1071.  
  1072. DMHRAPI HrDbgName(LPCSTR szCommand, LPSTR szResponse,
  1073.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1074. {
  1075.     char sz[256];
  1076.  
  1077.     if(FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1078.     {
  1079.         strcpy_s(g_dmGlobals.rgchDbgName, 256, sz);
  1080.         g_dmGlobals.bDirty = TRUE;
  1081.  
  1082.         return XBDM_NOERR;
  1083.     }
  1084.  
  1085.     strcpy_s(szResponse, cchResponse, g_dmGlobals.rgchDbgName);
  1086.     return XBDM_NOERR;
  1087. }
  1088.  
  1089. DMHRAPI HrDrivemap(LPCSTR szCommand, LPSTR szResponse,
  1090.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1091. {
  1092.     if(PchGetParam(szCommand, "internal", FALSE))
  1093.         g_dmGlobals.bDriveMap = TRUE;
  1094.     else
  1095.         g_dmGlobals.bDriveMap = FALSE;
  1096.  
  1097.     g_dmGlobals.bDirty = TRUE;
  1098.  
  1099.     return XBDM_NOERR;
  1100. }
  1101.  
  1102. DMHRAPI HrReportHelpInfo(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1103. {
  1104.     if((int)pdmcd->cch >= cchcmd)
  1105.         return XBDM_ENDOFLIST;
  1106.  
  1107.     strcpy_s((char*)pdmcc->Buffer, pdmcc->BufferSize, rgbcmd[pdmcd->cch].szName);
  1108.     pdmcd->cch++;
  1109.  
  1110.     return XBDM_NOERR;
  1111. }
  1112.  
  1113. DMHRAPI HrHelp(LPCSTR szCommand, LPSTR szResponse,
  1114.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1115. {
  1116.     if(!pdmcc)
  1117.         return E_FAIL;
  1118.  
  1119.     pdmcc->HandlingFunction = HrReportHelpInfo;
  1120.     pdmcc->BufferSize = 1;
  1121.     pdmcd->cch = 0;
  1122.    
  1123.     strcpy_s(szResponse, cchResponse, "command names follow");
  1124.  
  1125.     return XBDM_MULTIRESPONSE;
  1126. }
  1127.  
  1128. DMHRAPI HrReboot(LPCSTR szCommand, LPSTR szResponse,
  1129.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1130. {
  1131.     if(!pdmcc)
  1132.         return E_FAIL;
  1133.  
  1134.     FStopServ();
  1135.  
  1136.     HalReturnToFirmware(6);
  1137.     return XBDM_NOERR;
  1138. }
  1139.  
  1140. DMHRAPI HrSetSystemTime(LPCSTR szCommand, LPSTR szResponse,
  1141.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1142. {
  1143.     ULARGE_INTEGER lu, luUnused;
  1144.  
  1145.     if(!pdmcc)
  1146.         return E_FAIL;
  1147.    
  1148.     if(!FGetDwParam(szCommand, "clockhi", &lu.HighPart) || !FGetDwParam(szCommand, "clocklo", &lu.LowPart))
  1149.         return XBDM_CLOCKNOTSET;
  1150.  
  1151.     NtSetSystemTime(&lu, &luUnused);
  1152.     XnpNoteSystemTime();
  1153.  
  1154.     g_dmGlobals.fClockSet = TRUE;
  1155.  
  1156.     return XBDM_NOERR;
  1157. }
  1158.  
  1159. DMHRAPI HrGetSystemTime(LPCSTR szCommand, LPSTR szResponse,
  1160.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1161. {
  1162.     ULARGE_INTEGER lu;
  1163.  
  1164.     if(!pdmcc)
  1165.         return E_FAIL;
  1166.  
  1167.     if(!g_dmGlobals.fClockSet)
  1168.         return XBDM_CLOCKNOTSET;
  1169.  
  1170.     KeQuerySystemTime(&lu);
  1171.    
  1172.     RtlSnprintf(szResponse, cchResponse, "high=0x%x low=0x%x", lu.HighPart, lu.LowPart);
  1173.  
  1174.     return XBDM_NOERR;
  1175. }
  1176.  
  1177. DMHRAPI HrShutdown(LPCSTR szCommand, LPSTR szResponse,
  1178.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1179. {
  1180.     if(!pdmcc)
  1181.         return E_FAIL;
  1182.  
  1183.     FStopServ();
  1184.  
  1185.     HalReturnToFirmware(5);
  1186.     return XBDM_NOERR;
  1187. }
  1188.  
  1189. DMHRAPI HrSpew(LPCSTR szCommand, LPSTR szResponse,
  1190.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1191. {
  1192.     DbgPrint("SPEW: %s\n", szCommand);
  1193.     return XBDM_NOERR;
  1194. }
  1195.  
  1196. DMHRAPI HrReportXbeInfo(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1197. {
  1198.     PDM_XBE pdxbe = (PDM_XBE)pdmcc->CustomData;
  1199.     int i;
  1200.  
  1201.     if(pdmcc->BytesRemaining == 3)
  1202.     {
  1203.         DmFreePool(pdmcc->CustomData);
  1204.         return XBDM_ENDOFLIST;
  1205.     }
  1206.     else if(pdmcc->BytesRemaining == 2)
  1207.     {
  1208.         i = strlen(pdxbe->LaunchPath);
  1209.  
  1210.         pdxbe->LaunchPath[i++] = '"';
  1211.         pdxbe->LaunchPath[i + 1] = 0;
  1212.         memmove(pdxbe->LaunchPath + 6, pdxbe->LaunchPath, i++);
  1213.         memcpy(pdxbe->LaunchPath, "name=\"", 6);
  1214.  
  1215.         pdmcc->Buffer = pdxbe->LaunchPath;
  1216.         pdmcc->BytesRemaining++;
  1217.     }
  1218.     else if(pdmcc->BytesRemaining == 1)
  1219.     {
  1220.         RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "timestamp=0x%08x checksum=0x%08x", pdxbe->TimeStamp, pdxbe->CheckSum);
  1221.  
  1222.         pdmcc->BytesRemaining++;
  1223.     }
  1224.  
  1225.     return XBDM_NOERR;
  1226. }
  1227.  
  1228. DMHRAPI HrGetXbeInfo(LPCSTR szCommand, LPSTR szResponse,
  1229.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1230. {
  1231.     PDM_XBE pdxbe;
  1232.     DWORD dwFlags = 0;
  1233.     char sz[0x200];
  1234.     LPCSTR szName;
  1235.     HRESULT hr;
  1236.  
  1237.     if(!pdmcc)
  1238.         return E_FAIL;
  1239.  
  1240.     if(PchGetParam(szCommand, "running", FALSE))
  1241.         szName = NULL;
  1242.     else if(FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1243.     {
  1244.         szName = sz;
  1245.  
  1246.         if(PchGetParam(szCommand, "ondiskonly", FALSE))
  1247.             dwFlags = DM_XBEONDISKONLY;
  1248.     }
  1249.     else
  1250.     {
  1251.         strcpy_s(szResponse, cchResponse, "missing name");
  1252.         return E_FAIL;
  1253.     }
  1254.  
  1255.     pdxbe = (PDM_XBE)DmAllocatePoolWithTag(sizeof(DM_XBE), 'Xbdm');
  1256.     pdmcc->CustomData = pdxbe;
  1257.  
  1258.     if(!pdxbe)
  1259.         return E_OUTOFMEMORY;
  1260.  
  1261.     hr = DmGetXbeInfoEx(szName, pdxbe, dwFlags);
  1262.    
  1263.     if(NT_SUCCESS(hr))
  1264.     {
  1265.         pdmcc->HandlingFunction = HrReportXbeInfo;
  1266.         pdmcc->BytesRemaining = 1;
  1267.  
  1268.         hr = XBDM_MULTIRESPONSE;
  1269.     }
  1270.     else
  1271.         DmFreePool(pdxbe);
  1272.  
  1273.     return hr;
  1274. }
  1275.  
  1276. DMHRAPI HrReportDriveList(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1277. {
  1278.     CHAR sz[MAX_PATH];
  1279.     NTSTATUS st;
  1280.     ANSI_STRING as;
  1281.     OBJECT_ATTRIBUTES oa;
  1282.     BOOL bExists = FALSE;
  1283.     OBJECT_DIRECTORY_INFORMATION odi;
  1284.     HANDLE h;
  1285.     int i;
  1286.  
  1287. start:
  1288.     if(pdmcd->cch == 0)
  1289.     {
  1290.         // List from our interal list
  1291.  
  1292.         i = Drives[pdmcd->DriveList.CurrentDrive].Visibility;
  1293.  
  1294.         // Check verbosity
  1295.         if(i != 0 && !(i == 1 && !g_dmGlobals.bDriveMap))
  1296.         {
  1297.             // Get name
  1298.             strcpy(sz, Drives[pdmcd->DriveList.CurrentDrive].DriveName);
  1299.             i = strlen(sz);
  1300.             strcat(sz, ":\\");
  1301.  
  1302.             st = FCreateFile(&h, SYNCHRONIZE, sz, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  1303.                 FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
  1304.             if(NT_SUCCESS(st))
  1305.             {
  1306.                 sz[i] = 0;
  1307.                 bExists = TRUE;
  1308.                 NtClose(h);
  1309.             }
  1310.         }
  1311.  
  1312.         pdmcd->DriveList.CurrentDrive++;
  1313.  
  1314.         if(pdmcd->DriveList.CurrentDrive >= cchDrives)
  1315.         {
  1316.             // Move on to the actual object enumeration
  1317.             pdmcd->cch = 1;
  1318.  
  1319.             RtlInitAnsiString(&as, "\\??");
  1320.             oa.Attributes = OBJ_CASE_INSENSITIVE;
  1321.             oa.ObjectName = &as;
  1322.             oa.RootDirectory = NULL;
  1323.  
  1324.             pdmcd->DriveList.CurrentDrive = 0;
  1325.  
  1326.             st = NtOpenDirectoryObject(&pdmcd->h, &oa);
  1327.  
  1328.             if(FAILED(st))
  1329.             {
  1330.                 pdmcd->h = INVALID_HANDLE_VALUE;
  1331.                 pdmcd->cch = 2;
  1332.             }
  1333.         }
  1334.     }
  1335.     else if(pdmcd->cch == 1)
  1336.     {
  1337.         // List the objects
  1338.         st = NtQueryDirectoryObject(pdmcd->h, &odi, sizeof(odi), (pdmcd->DriveList.CurrentDrive == 0), (PULONG)&pdmcd->DriveList.CurrentDrive, NULL);
  1339.         if(NT_SUCCESS(st))
  1340.         {
  1341.             // Attempt to open the device that we found
  1342.             memcpy(sz, odi.Name.Buffer, odi.Name.Length);
  1343.  
  1344.             // But first, check the drive list
  1345.             sz[odi.Name.Length - 1] = 0;
  1346.             for(i = 0;i < cchDrives;i++)
  1347.             {
  1348.                 if(!strcmpi(Drives[i].DriveName, sz))
  1349.                 {
  1350.                     bExists = TRUE;
  1351.                     break;
  1352.                 }
  1353.             }
  1354.  
  1355.             if(bExists)
  1356.                 bExists = FALSE;
  1357.             else
  1358.             {
  1359.                 strcat(sz, ":\\");
  1360.  
  1361.                 st = FCreateFile(&h, SYNCHRONIZE, sz, NULL, 0,
  1362.                     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  1363.                     FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
  1364.                 if(NT_SUCCESS(st))
  1365.                 {
  1366.                     NtClose(h);
  1367.                     sz[odi.Name.Length - 1] = 0;
  1368.                     bExists = TRUE;
  1369.                 }
  1370.             }
  1371.         }
  1372.         else
  1373.         {
  1374.             NtClose(pdmcd->h);
  1375.             pdmcd->cch = 2;
  1376.         }
  1377.     }
  1378.     else
  1379.         return XBDM_ENDOFLIST;
  1380.  
  1381.     if(bExists)
  1382.         RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "drivename=\"%s\"", sz);
  1383.     else
  1384.         goto start;
  1385.  
  1386.     return XBDM_NOERR;
  1387. }
  1388.  
  1389. DMHRAPI HrGetDriveList(LPCSTR szCommand, LPSTR szResponse,
  1390.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1391. {
  1392.     if(!pdmcc)
  1393.         return E_FAIL;
  1394.  
  1395.     pdmcd->cch = 0;
  1396.     pdmcd->DriveList.CurrentDrive = 0;
  1397.     pdmcd->h = INVALID_HANDLE_VALUE;
  1398.    
  1399.     pdmcc->BytesRemaining = 1;
  1400.     pdmcc->HandlingFunction = HrReportDriveList;
  1401.  
  1402.     return XBDM_MULTIRESPONSE;
  1403. }
  1404.  
  1405. DMHRAPI HrReportDriveFreeSpace(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1406. {
  1407.     FILE_FS_SIZE_INFORMATION fsi;
  1408.     IO_STATUS_BLOCK iosb;
  1409.     DWORD dwBPU;
  1410.     ULARGE_INTEGER ulFree, ulTotal;
  1411.     NTSTATUS st;
  1412.  
  1413.     if(pdmcd->cch)
  1414.         return XBDM_ENDOFLIST;
  1415.  
  1416.     pdmcd->cch = 1;
  1417.  
  1418.     st = NtQueryVolumeInformationFile(pdmcd->h, &iosb, &fsi, sizeof(fsi), FileFsSizeInformation);
  1419.  
  1420.     if(FAILED(st))
  1421.     {
  1422.         RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "unknown error (%d)", st);
  1423.         return E_FAIL;
  1424.     }
  1425.  
  1426.     dwBPU = fsi.SectorsPerAllocationUnit * fsi.BytesPerSector;
  1427.  
  1428.     ulFree.QuadPart = fsi.AvailableAllocationUnits.QuadPart * dwBPU;
  1429.     ulTotal.QuadPart = fsi.TotalAllocationUnits.QuadPart * dwBPU;
  1430.  
  1431.     RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "freetocallerlo=0x%08x freetocallerhi=0x%08x totalbyteslo=0x%08x totalbyteshi=0x%08x totalfreebyteslo=0x%08x totalfreebyteshi=0x%08x",
  1432.         ulFree.LowPart, ulFree.HighPart, ulTotal.LowPart, ulTotal.HighPart, ulFree.LowPart, ulFree.HighPart);
  1433.  
  1434.     return XBDM_NOERR;
  1435. }
  1436.  
  1437. DMHRAPI HrGetDriveFreeSpace(LPCSTR szCommand, LPSTR szResponse,
  1438.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1439. {
  1440.     NTSTATUS st;
  1441.     char sz[MAX_PATH];
  1442.  
  1443.     if(!pdmcc)
  1444.         return E_FAIL;
  1445.  
  1446.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1447.     {
  1448.         strcpy(szResponse, "missing name");
  1449.         return E_FAIL;
  1450.     }
  1451.  
  1452.     st = FCreateFile(&pdmcd->h, FILE_READ_ATTRIBUTES, sz, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
  1453.         FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
  1454.  
  1455.     if(FAILED(st))
  1456.         return XBDM_CANNOTACCESS;
  1457.    
  1458.     pdmcd->cch = 0;
  1459.     pdmcc->HandlingFunction = HrReportDriveFreeSpace;
  1460.  
  1461.     return XBDM_MULTIRESPONSE;
  1462. }
  1463.  
  1464. DMHRAPI HrReportDirList(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1465. {
  1466.     NTSTATUS st;
  1467.     IO_STATUS_BLOCK iosb;
  1468.     FILE_DIRECTORY_INFORMATION fna;
  1469.     HRESULT hr = XBDM_NOERR;
  1470.  
  1471.     ZeroMemory(&fna, sizeof(fna));
  1472.     st = NtQueryDirectoryFile(pdmcd->h, NULL, NULL, NULL, &iosb,
  1473.         &fna, sizeof(fna), NULL, NULL);
  1474.  
  1475.     if(NT_SUCCESS(st))
  1476.     {
  1477.         RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "name=\"%s\" ", fna.FileName);
  1478.         GetFileAttrSz((char*)pdmcc->Buffer + strlen((char*)pdmcc->Buffer), fna.FileAttributes,
  1479.             &fna.LastWriteTime, &fna.CreationTime, &fna.EndOfFile);
  1480.     }
  1481.     else
  1482.     {
  1483.         NtClose(pdmcd->h);
  1484.         hr = XBDM_ENDOFLIST;
  1485.     }
  1486.  
  1487.     return hr;
  1488. }
  1489.  
  1490. DMHRAPI HrGetDirList(LPCSTR szCommand, LPSTR szResponse,
  1491.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1492. {
  1493.     NTSTATUS st;
  1494.     CHAR sz[MAX_PATH];
  1495.  
  1496.     if(!pdmcc)
  1497.         return E_FAIL;
  1498.  
  1499.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1500.     {
  1501.         strcpy(szResponse, "missing name");
  1502.         return E_FAIL;
  1503.     }
  1504.  
  1505.     pdmcc->BytesRemaining = 1;
  1506.     pdmcc->HandlingFunction = HrReportDirList;
  1507.  
  1508.     st = FCreateFile(&pdmcd->h, FILE_LIST_DIRECTORY | SYNCHRONIZE, sz, NULL, 0,
  1509.         FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
  1510.         FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
  1511.  
  1512.     return NT_SUCCESS(st) ? XBDM_MULTIRESPONSE : XBDM_CANNOTACCESS;
  1513. }
  1514.  
  1515. DMHRAPI HrDvdEject(LPCSTR szCommand, LPSTR szResponse,
  1516.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1517. {
  1518.     DWORD dwEject = 1;
  1519.  
  1520.     if(!pdmcc)
  1521.         return E_FAIL;
  1522.  
  1523.     FGetDwParam(szCommand, "eject", &dwEject);
  1524.  
  1525.     HalOpenCloseODDTray(dwEject);
  1526.  
  1527.     return XBDM_NOERR;
  1528. }
  1529.  
  1530. DMHRAPI HrDelete(LPCSTR szCommand, LPSTR szResponse,
  1531.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1532. {
  1533.     FILE_DISPOSITION_INFORMATION fdi;
  1534.     IO_STATUS_BLOCK iosb;
  1535.     char sz[MAX_PATH];
  1536.     NTSTATUS st;
  1537.     HANDLE h;
  1538.     BOOL b;
  1539.  
  1540.     if(!pdmcc)
  1541.         return E_FAIL;
  1542.  
  1543.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1544.     {
  1545.         strcpy_s(szResponse, cchResponse, "missing name");
  1546.         return E_FAIL;
  1547.     }
  1548.  
  1549.     b = (BOOL)PchGetParam(szCommand, "dir", FALSE);
  1550.  
  1551.     st = FCreateFile(&h, DELETE | SYNCHRONIZE, sz, NULL, 0, 0,
  1552.         FILE_OPEN, (b ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE)
  1553.         | FILE_SYNCHRONOUS_IO_NONALERT);
  1554.  
  1555.     if(FAILED(st))
  1556.         return XBDM_CANNOTACCESS;
  1557.  
  1558.     ZeroMemory(&fdi, sizeof(fdi));
  1559.     fdi.DeleteFile = TRUE;
  1560.  
  1561.     st = NtSetInformationFile(h, &iosb, &fdi, sizeof(fdi), FileDispositionInformation);
  1562.     NtClose(h);
  1563.  
  1564.     if(FAILED(st))
  1565.         return XBDM_CANNOTACCESS;
  1566.  
  1567.     return XBDM_NOERR;
  1568. }
  1569.  
  1570. DMHRAPI HrCreateDirectory(LPCSTR szCommand, LPSTR szResponse,
  1571.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1572. {
  1573.     char sz[MAX_PATH];
  1574.     NTSTATUS st;
  1575.     HANDLE h;
  1576.  
  1577.     if(!pdmcc)
  1578.         return E_FAIL;
  1579.  
  1580.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1581.     {
  1582.         strcpy_s(szResponse, cchResponse, "missing name");
  1583.         return E_FAIL;
  1584.     }
  1585.  
  1586.     st = FCreateFile(&h, FILE_LIST_DIRECTORY | SYNCHRONIZE, sz,
  1587.         NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_DIRECTORY_FILE |
  1588.         FILE_SYNCHRONOUS_IO_NONALERT);
  1589.  
  1590.     if(FAILED(st))
  1591.     {
  1592.         if(st == STATUS_OBJECT_NAME_COLLISION)
  1593.             return XBDM_ALREADYEXISTS;
  1594.         return XBDM_CANNOTCREATE;
  1595.     }
  1596.  
  1597.     NtClose(h);
  1598.     return XBDM_NOERR;
  1599. }
  1600.  
  1601. DMHRAPI HrRenameFile(LPCSTR szCommand, LPSTR szResponse,
  1602.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1603. {
  1604.     char sz[MAX_PATH];
  1605.     char szNew[MAX_PATH];
  1606.     IO_STATUS_BLOCK iosb;
  1607.     NTSTATUS st;
  1608.     HANDLE h;
  1609.     FILE_RENAME_INFORMATION fri;
  1610.  
  1611.     if(!pdmcc)
  1612.         return E_FAIL;
  1613.  
  1614.     if(!FGetSzParam(szCommand, "newname", sz, sizeof(sz)))
  1615.     {
  1616.         strcpy_s(szResponse, cchResponse, "missing newname");
  1617.         return E_FAIL;
  1618.     }
  1619.     if(FAILED(FFileNameToObName(sz, szNew, sizeof(szNew))))
  1620.     {
  1621.         strcpy_s(szResponse, cchResponse, "new name does not exist");
  1622.         return XBDM_NOSUCHFILE;
  1623.     }
  1624.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1625.     {
  1626.         strcpy_s(szResponse, cchResponse, "missing name");
  1627.         return E_FAIL;
  1628.     }
  1629.  
  1630.     st = FCreateFile(&h, GENERIC_WRITE | SYNCHRONIZE, sz, NULL, 0, 0,
  1631.         FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT);
  1632.    
  1633.     if(FAILED(st))
  1634.         return XBDM_CANNOTACCESS;
  1635.  
  1636.     ZeroMemory(&fri, sizeof(fri));
  1637.    
  1638.     RtlInitAnsiString(&fri.FileName, szNew);
  1639.     fri.ReplaceIfExists = FALSE;
  1640.     fri.RootDirectory = NULL;
  1641.  
  1642.     st = NtSetInformationFile(h, &iosb, &fri, sizeof(fri), FileRenameInformation);
  1643.     NtClose(h);
  1644.  
  1645.     if(st == STATUS_NOT_SAME_DEVICE)
  1646.         return XBDM_MUSTCOPY;
  1647.  
  1648.     if(FAILED(st))
  1649.         return XBDM_CANNOTCREATE;
  1650.  
  1651.     return XBDM_NOERR;
  1652. }
  1653.  
  1654. DMHRAPI HrReportFileAttributes(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1655. {
  1656.     if(pdmcd->cch)
  1657.         return XBDM_ENDOFLIST;
  1658.  
  1659.     pdmcd->cch = 1;
  1660.  
  1661.     GetFileAttrSz((LPSTR)pdmcc->Buffer, pdmcd->fni.fni.FileAttributes,
  1662.         &pdmcd->fni.fni.LastWriteTime, &pdmcd->fni.fni.CreationTime,
  1663.         &pdmcd->fni.fni.EndOfFile);
  1664.  
  1665.     return XBDM_NOERR;
  1666. }
  1667.  
  1668. DMHRAPI HrGetFileAttr(LPCSTR szCommand, LPSTR szResponse,
  1669.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1670. {
  1671.     char sz[MAX_PATH];
  1672.     char osz[MAX_PATH];
  1673.     ANSI_STRING as;
  1674.     NTSTATUS st;
  1675.     OBJECT_ATTRIBUTES oa;
  1676.  
  1677.     if(!pdmcc)
  1678.         return E_FAIL;
  1679.  
  1680.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1681.     {
  1682.         strcpy_s(szResponse, cchResponse, "missing name");
  1683.         return E_FAIL;
  1684.     }
  1685.  
  1686.     if(FAILED(FFileNameToObName(sz, osz, sizeof(osz))))
  1687.         return XBDM_NOSUCHFILE;
  1688.  
  1689.     RtlInitAnsiString(&as, osz);
  1690.     oa.Attributes = OBJ_CASE_INSENSITIVE;
  1691.     oa.RootDirectory = NULL;
  1692.     oa.ObjectName = &as;
  1693.  
  1694.     pdmcc->HandlingFunction = HrReportFileAttributes;
  1695.     pdmcc->BytesRemaining = 1;
  1696.     pdmcd->cch = 0;
  1697.    
  1698.     st = NtQueryFullAttributesFile(&oa, &pdmcd->fni.fni);
  1699.     return NT_SUCCESS(st) ? XBDM_MULTIRESPONSE : XBDM_NOSUCHFILE;
  1700. }
  1701.  
  1702. DMHRAPI HrSetFileAttr(LPCSTR szCommand, LPSTR szResponse,
  1703.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1704. {
  1705.     NTSTATUS st;
  1706.     HANDLE h;
  1707.     IO_STATUS_BLOCK iosb;
  1708.     char sz[MAX_PATH];
  1709.     FILE_NETWORK_OPEN_INFORMATION fna;
  1710.     FILE_BASIC_INFORMATION fba;
  1711.     DWORD dwAttrMask = 0;
  1712.     DWORD dwAttrNew = 0;
  1713.     DWORD dwT = 0;
  1714.  
  1715.     if(!pdmcc)
  1716.         return E_FAIL;
  1717.    
  1718.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  1719.     {
  1720.         strcpy_s(szResponse, cchResponse, "missing name");
  1721.         return E_FAIL;
  1722.     }
  1723.  
  1724.     st = FCreateFile(&h, SYNCHRONIZE, sz, NULL, 0,
  1725.         FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
  1726.         FILE_SYNCHRONOUS_IO_NONALERT);
  1727.    
  1728.     if(FAILED(st))
  1729.         return XBDM_CANNOTACCESS;
  1730.  
  1731.     st = NtQueryInformationFile(h, &iosb, &fna, sizeof(fna), FileNetworkOpenInformation);
  1732.  
  1733.     if(FAILED(st))
  1734.     {
  1735.         NtClose(h);
  1736.         return XBDM_CANNOTACCESS;
  1737.     }
  1738.  
  1739.     ZeroMemory(&fba, sizeof(fba));
  1740.     if(FGetDwParam(szCommand, "readonly", &dwT))
  1741.     {
  1742.         dwAttrMask |= FILE_ATTRIBUTE_READONLY;
  1743.         if(dwT)
  1744.             dwAttrNew |= FILE_ATTRIBUTE_READONLY;
  1745.     }
  1746.     if(FGetDwParam(szCommand, "hidden", &dwT))
  1747.     {
  1748.         dwAttrMask |= FILE_ATTRIBUTE_HIDDEN;
  1749.         if(dwT)
  1750.             dwAttrNew |= FILE_ATTRIBUTE_HIDDEN;
  1751.     }
  1752.  
  1753.     FGetDwParam(szCommand, "createhi", (DWORD*)&fba.CreationTime.HighPart);
  1754.     FGetDwParam(szCommand, "createlo", (DWORD*)&fba.ChangeTime.LowPart);
  1755.     FGetDwParam(szCommand, "changehi", (DWORD*)&fba.LastWriteTime.HighPart);
  1756.     FGetDwParam(szCommand, "changelo", (DWORD*)&fba.LastWriteTime.LowPart);
  1757.  
  1758.     fba.FileAttributes = fna.FileAttributes ^ ((fna.FileAttributes ^ dwAttrNew) & dwAttrMask);
  1759.  
  1760.     if(!fba.FileAttributes)
  1761.         fba.FileAttributes = FILE_ATTRIBUTE_NORMAL;
  1762.  
  1763.     st = NtSetInformationFile(h, &iosb, &fba, sizeof(fba), FileBasicInformation);
  1764.  
  1765.     NtClose(h);
  1766.  
  1767.     return NT_SUCCESS(st) ? XBDM_NOERR : XBDM_CANNOTACCESS;
  1768. }
  1769.  
  1770. DMHRAPI HrReportMemoryEx(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1771. {
  1772.     DWORD chars, addr, read = 0;
  1773.     BYTE mem;
  1774.  
  1775.     if(!pdmcd->cch)
  1776.     {
  1777.         pdmcc->BytesRemaining = 0;
  1778.         DmFreePool(pdmcc->Buffer);
  1779.  
  1780.         return XBDM_ENDOFLIST;
  1781.     }
  1782.  
  1783.     chars = pdmcd->cch;
  1784.     if(chars > 0x400)
  1785.     {
  1786.         chars = 0x400;
  1787.         ((PBYTE)pdmcc->Buffer)[1] = 0x00;
  1788.     }
  1789.     else
  1790.         ((PBYTE)pdmcc->Buffer)[1] = 0x80;
  1791.  
  1792.     ((PBYTE)pdmcc->Buffer)[0] = 0;
  1793.  
  1794.     for(addr = pdmcd->mem.Address;addr < pdmcd->mem.Address + chars;addr++)
  1795.     {
  1796.         if(FGetMemory(addr, &mem))
  1797.         {
  1798.             ((PBYTE)pdmcc->Buffer)[addr - pdmcd->mem.Address + 2] = mem;
  1799.             read++;
  1800.         }
  1801.         else
  1802.         {
  1803.             pdmcd->cch = 0;
  1804.             ((PBYTE)pdmcc->Buffer)[1] = 0x80;
  1805.             break;
  1806.         }
  1807.     }
  1808.  
  1809.     *(PWORD)pdmcc->Buffer |= _byteswap_ushort((WORD)read);
  1810.    
  1811.     if(pdmcd->cch)
  1812.         pdmcd->cch -= read;
  1813.  
  1814.     pdmcd->mem.Address += read;
  1815.    
  1816.     pdmcc->BytesRemaining = 1;
  1817.     pdmcc->DataSize = read + 2;
  1818.  
  1819.     return XBDM_NOERR;
  1820. }
  1821.  
  1822. DMHRAPI HrGetMemoryEx(LPCSTR szCommand, LPSTR szResponse,
  1823.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1824. {
  1825.     DWORD dwAddr, dwLength;
  1826.  
  1827.     if(!pdmcc)
  1828.         return E_FAIL;
  1829.  
  1830.     if(!FGetNamedDwParam(szCommand, "addr", &dwAddr, szResponse)
  1831.         || !FGetNamedDwParam(szCommand, "length", &dwLength, szResponse))
  1832.         return E_FAIL;
  1833.  
  1834.     pdmcc->BufferSize = 0x402;
  1835.     if(!(pdmcc->Buffer = DmAllocatePoolWithTag(pdmcc->BufferSize, 'xbdm')))
  1836.         return E_OUTOFMEMORY;
  1837.  
  1838.     pdmcc->BytesRemaining = 1;
  1839.     pdmcc->HandlingFunction = HrReportMemoryEx;
  1840.     pdmcd->cch = dwLength;
  1841.     pdmcd->mem.Address = dwAddr;
  1842.  
  1843.     return XBDM_BINRESPONSE;
  1844. }
  1845.  
  1846. DMHRAPI HrReportMemory(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1847. {
  1848.     DWORD chars;
  1849.     DWORD addr;
  1850.     BYTE b;
  1851.  
  1852.     if(!pdmcd->cch)
  1853.         return XBDM_ENDOFLIST;
  1854.  
  1855.     chars = pdmcd->cch;
  1856.     if(chars > 64)
  1857.         chars = 64;
  1858.  
  1859.     for(addr = pdmcd->mem.Address;addr < pdmcd->mem.Address + chars;addr++)
  1860.     {
  1861.         if(FGetMemory(addr, &b))
  1862.         {
  1863.             ((PBYTE)pdmcc->Buffer)[(addr - pdmcd->mem.Address) * 2] = rgchHex[(b >> 4) & 0xf];
  1864.             ((PBYTE)pdmcc->Buffer)[(addr - pdmcd->mem.Address) * 2 + 1] = rgchHex[b & 0xf];
  1865.         }
  1866.         else
  1867.             ((PBYTE)pdmcc->Buffer)[(addr - pdmcd->mem.Address) * 2] = ((PBYTE)pdmcc->Buffer)[(addr - pdmcd->mem.Address) * 2 + 1] = '?';
  1868.     }
  1869.  
  1870.     ((PBYTE)pdmcc->Buffer)[(addr - pdmcd->mem.Address) * 2] = 0;
  1871.  
  1872.     pdmcd->cch -= chars;
  1873.     pdmcd->mem.Address += chars;
  1874.  
  1875.     return XBDM_NOERR;
  1876. }
  1877.  
  1878. DMHRAPI HrGetMemory(LPCSTR szCommand, LPSTR szResponse,
  1879.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1880. {
  1881.     DWORD dwAddr, dwLength;
  1882.  
  1883.     if(!pdmcc)
  1884.         return E_FAIL;
  1885.  
  1886.     if(!FGetNamedDwParam(szCommand, "addr", &dwAddr, szResponse)
  1887.         || !FGetNamedDwParam(szCommand, "length", &dwLength, szResponse))
  1888.         return E_FAIL;
  1889.  
  1890.     strcpy_s(szResponse, cchResponse, "memory data follows");
  1891.  
  1892.     pdmcc->BytesRemaining = 1;
  1893.     pdmcc->HandlingFunction = HrReportMemory;
  1894.     pdmcd->cch = dwLength;
  1895.     pdmcd->mem.Address = dwAddr;
  1896.  
  1897.     return XBDM_MULTIRESPONSE;
  1898. }
  1899.  
  1900. DMHRAPI HrSetMemory(LPCSTR szCommand, LPSTR szResponse,
  1901.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1902. {
  1903.     int i;
  1904.     DWORD addr;
  1905.     LPCSTR data;
  1906.     char rgch[5];
  1907.     DWORD page;
  1908.     BOOL pageValid;
  1909.     BYTE b;
  1910.     int count = 0;
  1911.  
  1912.     if(!pdmcc)
  1913.         return E_FAIL;
  1914.  
  1915.     if(!FGetNamedDwParam(szCommand, "addr", &addr, szResponse))
  1916.         return E_FAIL;
  1917.  
  1918.     data = PchGetParam(szCommand, "data", FALSE);
  1919.     page = addr + 0x1000;
  1920.    
  1921.     rgch[0] = '0';
  1922.     rgch[1] = 'x';
  1923.     rgch[4] = 0;
  1924.  
  1925.     if(data)
  1926.     {
  1927.         for(;;count++, addr++)
  1928.         {
  1929.             if(FIsSpace(*data))
  1930.                 break;
  1931.             for(i = 0;i < 2;i++)
  1932.             {
  1933.                 if(!(*data >= '0' && *data <= '9' ||
  1934.                     *data >= 'a' && *data <= 'f' ||
  1935.                     *data >= 'A' && *data <= 'F'))
  1936.                 {
  1937.                         strcpy(szResponse, "syntax error in data");
  1938.                         return E_FAIL;
  1939.                 }
  1940.                 rgch[i + 2] = *data++;
  1941.             }
  1942.             b = (BYTE)DwFromSz(rgch, NULL);
  1943.             if((addr ^ page) & 0xFFFFF000)
  1944.             {
  1945.                 page = addr & 0xFFFFF000;
  1946.                 pageValid = MmIsAddressValid((LPVOID)addr);
  1947.             }
  1948.             if(pageValid)
  1949.                 DmSetMemory((PVOID)addr, 1, &b, NULL);
  1950.             else
  1951.             {
  1952.                 RtlSnprintf(szResponse, cchResponse, "set %d bytes", count);
  1953.                 return XBDM_MEMUNMAPPED;
  1954.             }
  1955.         }
  1956.     }
  1957.  
  1958.     RtlSnprintf(szResponse, cchResponse, "set %d bytes", count);
  1959.     return XBDM_NOERR;
  1960. }
  1961.  
  1962. DMHRAPI HrReportModules(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  1963. {
  1964.     DMN_MODLOAD_EX dmnex;
  1965.  
  1966.     if(pdmcc->BytesRemaining == 2)
  1967.         return XBDM_ENDOFLIST;
  1968.  
  1969.     if(FAILED(DmWalkLoadedModulesEx((PDM_WALK_MODULES*)&pdmcd->rgb, &dmnex)))
  1970.     {
  1971.         DmCloseLoadedModules((PDM_WALK_MODULES)pdmcd->rgb);
  1972.         pdmcc->BytesRemaining++;
  1973.     }
  1974.    
  1975.     RtlSnprintf((LPSTR)pdmcc->Buffer, pdmcc->BufferSize,
  1976.         "name=\"%s\" base=0x%08x size=0x%08x check=0x%08x timestamp=0x%08x pdata=0x%08x psize=0x%08x %sthread=0x%08x osize=0x%08x",
  1977.         dmnex.Name, dmnex.BaseAddress, dmnex.Size, dmnex.CheckSum, dmnex.TimeStamp, dmnex.PDataAddress, dmnex.PDataSize,
  1978.         dmnex.Flags & DMN_MODFLAG_TLS ? "" : "dll", dmnex.ThreadId, dmnex.OriginalSize);
  1979.  
  1980.     return XBDM_NOERR;
  1981. }
  1982.  
  1983. DMHRAPI HrGetModules(LPCSTR szCommand, LPSTR szResponse,
  1984.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1985. {
  1986.     if(!pdmcc)
  1987.         return E_FAIL;
  1988.  
  1989.     pdmcd->rgb = NULL;
  1990.     pdmcc->HandlingFunction = HrReportModules;
  1991.     pdmcc->BytesRemaining = 1;
  1992.  
  1993.     return XBDM_MULTIRESPONSE;
  1994. }
  1995.  
  1996. DMHRAPI HrStop(LPCSTR szCommand, LPSTR szResponse,
  1997.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  1998. {
  1999.     if(!pdmcc)
  2000.         return E_FAIL;
  2001.  
  2002.     return DwChangeExecState(DMN_EXEC_STOP, TRUE, TRUE, FALSE);
  2003. }
  2004.  
  2005. DMHRAPI HrGo(LPCSTR szCommand, LPSTR szResponse,
  2006.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2007. {
  2008.     if(!pdmcc)
  2009.         return E_FAIL;
  2010.  
  2011.     return DwChangeExecState(DMN_EXEC_START, TRUE, TRUE, FALSE);
  2012. }
  2013.  
  2014. DMHRAPI HrReportScreenshot(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  2015. {
  2016.     if(pdmcd->cch == 0)
  2017.     {
  2018.         RtlSnprintf((LPSTR)pdmcc->Buffer, pdmcc->BufferSize,
  2019.             "pitch=0x%08x width=0x%08x height=0x%08x format=0x%08x offsetx=0x%08x offsety=0x%08x, framebuffersize=0x%08x sw=0x%08x sh=0x%08x colorspace=0x%x\r\n",
  2020.             pdmcd->screen.p, pdmcd->screen.w, pdmcd->screen.h, pdmcd->screen.fmt, 0, 0, pdmcd->screen.size, pdmcd->screen.sw, pdmcd->screen.sh, 0);
  2021.        
  2022.         pdmcd->cch = 1;
  2023.         pdmcc->DataSize = strlen((char*)pdmcc->Buffer);
  2024.     }
  2025.     else if(pdmcd->cch == 1)
  2026.     {
  2027.         pdmcc->Buffer = (PVOID)pdmcd->screen.szFrame;
  2028.         pdmcc->DataSize = pdmcc->BytesRemaining;
  2029.         pdmcd->cch = 2;
  2030.     }
  2031.     else
  2032.     {
  2033.         if(NT_SUCCESS(pdmcd->hr))
  2034.             DwChangeExecState(DMN_EXEC_START, TRUE, FALSE, FALSE);
  2035.  
  2036.         return XBDM_ENDOFLIST;
  2037.     }
  2038.  
  2039.     return XBDM_NOERR;
  2040. }
  2041.  
  2042. DMHRAPI HrScreenshot(LPCSTR szCommand, LPSTR szResponse,
  2043.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2044. {
  2045.     DWORD dwStart, ptrOffset;
  2046.     char *frameBuffer;
  2047.     LPDWORD lpgpu = (LPDWORD)0x7FC81740;
  2048.     DISPLAY_INFORMATION display;
  2049.     DWORD w, h, p, size;
  2050.     DWORD vw, vh, vp, vs;
  2051.  
  2052.     if(!pdmcc)
  2053.         return E_FAIL;
  2054.  
  2055.     pdmcd->hr = DwChangeExecState(DMN_EXEC_STOP, TRUE, FALSE, FALSE);
  2056.  
  2057.     dwStart = *KeTimeStampBundle;
  2058.     while((*lpgpu & 0x80000000) && (*KeTimeStampBundle - dwStart < 5000))
  2059.         Sleep(100);
  2060.  
  2061.     if(*lpgpu & 0x80000000)
  2062.     {
  2063.         if(NT_SUCCESS(pdmcd->hr))
  2064.             DwChangeExecState(DMN_EXEC_START, TRUE, FALSE, FALSE);
  2065.         strcpy_s(szResponse, cchResponse, "can't lock GPU");
  2066.         return E_FAIL;
  2067.     }
  2068.  
  2069.     ptrOffset = *((DWORD*)0x7FC86110);
  2070.     frameBuffer = (char*)(0xC0000000 + ptrOffset);
  2071.     if(!MmIsAddressValid(frameBuffer)) {
  2072.         frameBuffer = (char*)(0xA0000000 + ptrOffset);
  2073.         if(!MmIsAddressValid(frameBuffer)) {
  2074.             frameBuffer = (char*)(0xDFFFF000 + ptrOffset);
  2075.         }
  2076.     }
  2077.  
  2078.     VdGetCurrentDisplayInformation(&display);
  2079.     w = display.FrontBufferWidth;
  2080.     h = display.FrontBufferHeight;
  2081.     p = w * 4;
  2082.     size = h * p;
  2083.  
  2084.     vw = w;vh = h;
  2085.     if(vw % 128)
  2086.         vw += (128 - vw % 128);
  2087.     if(vh % 128)
  2088.         vh += (128 - vh % 128);
  2089.     vp = vw * 4;
  2090.     vs = vh * vp;
  2091.  
  2092.     pdmcc->HandlingFunction = HrReportScreenshot;
  2093.     pdmcc->BytesRemaining = vs;
  2094.     pdmcd->cch = 0;
  2095.    
  2096.     pdmcd->screen.fmt = (((*((UINT*)0x7FC86104) >> 24) & 7) == 0) ? D3DFMT_A8R8G8B8 : D3DFMT_A2R10G10B10;
  2097.  
  2098.     pdmcd->screen.w = w;
  2099.     pdmcd->screen.h = h;
  2100.     pdmcd->screen.sw = display.DisplayWidth;
  2101.     pdmcd->screen.sh = display.DisplayHeight;
  2102.     pdmcd->screen.p = p;
  2103.     pdmcd->screen.size = vs;
  2104.     pdmcd->screen.szFrame = frameBuffer;
  2105.  
  2106.     return XBDM_BINRESPONSE;
  2107. }
  2108.  
  2109. DMHRAPI HrReportWalkMemory(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  2110. {
  2111.     DWORD dwAddr, dwLength, dwProtect, dwPhys;
  2112.  
  2113.     dwAddr = pdmcd->cch;
  2114.  
  2115.     if(dwAddr == 0xFFFFFFFF)
  2116.         return XBDM_ENDOFLIST;
  2117.  
  2118.     while(!MmIsAddressValid((PVOID)dwAddr))
  2119.     {
  2120.         if(dwAddr == 0xFFFFF000)
  2121.             return XBDM_ENDOFLIST;
  2122.         dwAddr += 0x1000;
  2123.     }
  2124.  
  2125.     // dwAddr now contains a valid page start
  2126.  
  2127.     dwProtect = XQueryMemoryProtect((LPVOID)dwAddr);
  2128.  
  2129.     // Calc the length of the page
  2130.     dwLength = 0x1000;
  2131.  
  2132.     while(MmIsAddressValid((PVOID)(dwAddr + dwLength)) && (XQueryMemoryProtect((LPVOID)(dwAddr + dwLength)) == dwProtect))
  2133.     {
  2134.         if((dwAddr + dwLength) == 0)
  2135.             break;
  2136.         dwLength += 0x1000;
  2137.     }
  2138.  
  2139.     // Now dwLength contains the page length
  2140.     if((dwAddr + dwLength) == 0)
  2141.         pdmcd->cch = 0xFFFFFFFF;
  2142.     else
  2143.         pdmcd->cch = dwAddr + dwLength;
  2144.  
  2145.     dwPhys = MmGetPhysicalAddress((PVOID)dwAddr);
  2146.  
  2147.     RtlSnprintf((LPSTR)pdmcc->Buffer, pdmcc->BufferSize, "base=0x%0.8x size=0x%0.8x protect=0x%0.8x phys=0x%0.8x",
  2148.         dwAddr, dwLength, dwProtect, dwPhys);
  2149.     return XBDM_NOERR;
  2150. }
  2151.  
  2152. DMHRAPI HrWalkMemory(LPCSTR szCommand, LPSTR szResponse,
  2153.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2154. {
  2155.     if(!pdmcc)
  2156.         return E_FAIL;
  2157.  
  2158.     pdmcd->cch = 0;
  2159.     pdmcc->BytesRemaining = 1;
  2160.     pdmcc->HandlingFunction = HrReportWalkMemory;
  2161.  
  2162.     strcpy_s(szResponse, cchResponse, "Valid Virtual Address Ranges Follow");
  2163.     return XBDM_MULTIRESPONSE;
  2164. }
  2165.  
  2166. DMHRAPI HrSetColor(LPCSTR szCommand, LPSTR szResponse,
  2167.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2168. {
  2169.     char sz[0x10];
  2170.  
  2171.     sz[0] = 0;
  2172.     FGetSzParam(szCommand, "name", sz, sizeof(sz));
  2173.  
  2174.     g_dmGlobals.dwConsoleColor = 0;
  2175.  
  2176.     if(!stricmp(sz, "black"))
  2177.         g_dmGlobals.dwConsoleColor = CONSOLE_COLOR_FLAG_BLACK;
  2178.     else if(!stricmp(sz, "blue"))
  2179.         g_dmGlobals.dwConsoleColor = CONSOLE_COLOR_FLAG_BLACK | CONSOLE_COLOR_FLAG_BLUE;
  2180.     else if(!stricmp(sz, "bluegray"))
  2181.         g_dmGlobals.dwConsoleColor = CONSOLE_COLOR_FLAG_WHITE | CONSOLE_COLOR_FLAG_BLUE;
  2182.     else if(!stricmp(sz, "nosidecar"))
  2183.         g_dmGlobals.dwConsoleColor = CONSOLE_COLOR_FLAG_NOSIDECAR;
  2184.     else if(!stricmp(sz, "white"))
  2185.         g_dmGlobals.dwConsoleColor = CONSOLE_COLOR_FLAG_WHITE;
  2186.  
  2187.     g_dmGlobals.bDirty = TRUE;
  2188.  
  2189.     return XBDM_NOERR;
  2190. }
  2191.  
  2192. DMHRAPI HrSendFileData(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  2193. {
  2194.     NTSTATUS st;
  2195.     DWORD cb;
  2196.  
  2197.     if(pdmcc->BytesRemaining == 1)
  2198.     {
  2199.         // Send the length
  2200.         *(LPDWORD)pdmcc->Buffer = _byteswap_ulong(pdmcd->cch);
  2201.         pdmcc->DataSize = 4;
  2202.         pdmcc->BytesRemaining = 2;
  2203.     }
  2204.     else if(pdmcc->BytesRemaining == 2)
  2205.     {
  2206.         // Send the file data
  2207.         cb = pdmcc->BufferSize;
  2208.         if(cb > pdmcd->cch)
  2209.             cb = pdmcd->cch;
  2210.         st = FReadFile(pdmcd->h, pdmcc->Buffer, cb);
  2211.         if(FAILED(st))
  2212.             ZeroMemory(pdmcc->Buffer, cb);
  2213.         pdmcd->cch -= cb;
  2214.         pdmcc->DataSize = cb;
  2215.  
  2216.         if(pdmcd->cch == 0)
  2217.             pdmcc->BytesRemaining = 3;
  2218.     }
  2219.     else
  2220.     {
  2221.         // Close and exit
  2222.         NtClose(pdmcd->h);
  2223.         DmFreePool(pdmcc->Buffer);
  2224.  
  2225.         return XBDM_ENDOFLIST;
  2226.     }
  2227.  
  2228.     return XBDM_NOERR;
  2229. }
  2230.  
  2231. DMHRAPI HrGetFile(LPCSTR szCommand, LPSTR szResponse,
  2232.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2233. {
  2234.     NTSTATUS st;
  2235.     IO_STATUS_BLOCK iosb;
  2236.     char sz[MAX_PATH];
  2237.     FILE_NETWORK_OPEN_INFORMATION fni;
  2238.  
  2239.     if(!pdmcc)
  2240.         return E_FAIL;
  2241.  
  2242.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  2243.     {
  2244.         strcpy_s(szResponse, cchResponse, "missing name");
  2245.         return E_FAIL;
  2246.     }
  2247.    
  2248.     st = FCreateFile(&pdmcd->h, GENERIC_READ | SYNCHRONIZE, sz,
  2249.         NULL, 0, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT);
  2250.  
  2251.     if(FAILED(st))
  2252.         return XBDM_CANNOTACCESS;
  2253.  
  2254.     st = NtQueryInformationFile(pdmcd->h, &iosb, &fni, sizeof(fni), FileNetworkOpenInformation);
  2255.  
  2256.     if(FAILED(st))
  2257.     {
  2258.         NtClose(pdmcd->h);
  2259.         return E_UNEXPECTED;
  2260.     }
  2261.  
  2262.     if(fni.EndOfFile.HighPart)
  2263.     {
  2264.         NtClose(pdmcd->h);
  2265.  
  2266.         strcpy_s(szResponse, cchResponse, "file is too big");
  2267.         return E_FAIL;
  2268.     }
  2269.  
  2270.     pdmcc->BufferSize = 0x3000;
  2271.     pdmcc->Buffer = DmAllocatePoolWithTag(pdmcc->BufferSize, 'bdbd');
  2272.  
  2273.     if(pdmcc->Buffer == NULL)
  2274.     {
  2275.         NtClose(pdmcd->h);
  2276.         return E_OUTOFMEMORY;
  2277.     }
  2278.  
  2279.     pdmcd->cch = fni.EndOfFile.LowPart;
  2280.     pdmcc->BytesRemaining = 1;
  2281.     pdmcc->HandlingFunction = HrSendFileData;
  2282.  
  2283.     return XBDM_BINRESPONSE;
  2284. }
  2285.  
  2286. DMHRAPI HrRecieveFileData(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  2287. {
  2288.     FILE_DISPOSITION_INFORMATION fdi;
  2289.     IO_STATUS_BLOCK iosb;
  2290.     NTSTATUS st;
  2291.  
  2292.     if(pdmcc->DataSize)
  2293.     {
  2294.         pdmcd->ib += pdmcc->DataSize;
  2295.         pdmcc->BytesRemaining -= pdmcc->DataSize;
  2296.     }
  2297.     else if(pdmcc->BytesRemaining)
  2298.     {
  2299.         pdmcc->BytesRemaining = 0;
  2300.         fdi.DeleteFile = TRUE;
  2301.         NtSetInformationFile(pdmcd->h, &iosb, &fdi, sizeof(fdi), FileDispositionInformation);
  2302.         pdmcd->fError = TRUE;
  2303.     }
  2304.  
  2305.     if(!pdmcc->BytesRemaining || pdmcd->ib == pdmcd->cchBuf)
  2306.     {
  2307.         if(pdmcd->h != INVALID_HANDLE_VALUE)
  2308.         {
  2309.             st = NtWriteFile(pdmcd->h, NULL, NULL, NULL, &iosb,
  2310.                 pdmcd->rgb, pdmcd->ib, NULL);
  2311.  
  2312.             if(FAILED(st))
  2313.             {
  2314.                 fdi.DeleteFile = TRUE;
  2315.                 NtSetInformationFile(pdmcd->h, &iosb, &fdi, sizeof(fdi), FileDispositionInformation);
  2316.                 NtClose(pdmcd->h);
  2317.                 pdmcd->fError = TRUE;
  2318.                 pdmcd->h = INVALID_HANDLE_VALUE;
  2319.             }
  2320.             else if(!pdmcc->BytesRemaining)
  2321.             {
  2322.                 NtClose(pdmcd->h);
  2323.                 pdmcd->h = INVALID_HANDLE_VALUE;
  2324.             }
  2325.         }
  2326.  
  2327.         pdmcc->Buffer = (char*)pdmcc->Buffer - pdmcd->ib;
  2328.         pdmcd->ib = 0;
  2329.  
  2330.         if(!pdmcc->BytesRemaining && pdmcc->Buffer)
  2331.             DmFreePool(pdmcd->rgb);
  2332.     }
  2333.  
  2334.     if(pdmcd->rgb)
  2335.     {
  2336.         pdmcc->Buffer = pdmcd->rgb + pdmcd->ib;
  2337.         pdmcc->BufferSize = pdmcd->cchBuf - pdmcd->ib;
  2338.     }
  2339.  
  2340.     if(pdmcd->fError)
  2341.     {
  2342.         DmFreePool(pdmcd->rgb);
  2343.         NtClose(pdmcd->h);
  2344.         pdmcd->h = INVALID_HANDLE_VALUE;
  2345.     }
  2346.  
  2347.     return pdmcd->fError ? E_UNEXPECTED : XBDM_NOERR;
  2348. }
  2349.  
  2350. DMHRAPI HrSendFile(LPCSTR szCommand, LPSTR szResponse,
  2351.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2352. {
  2353.     NTSTATUS st;
  2354.     char sz[MAX_PATH];
  2355.     IO_STATUS_BLOCK iosb;
  2356.     FILE_DISPOSITION_INFORMATION fdi;
  2357.     LARGE_INTEGER liSize;
  2358.  
  2359.     if(!pdmcc)
  2360.         return E_FAIL;
  2361.  
  2362.     if(!FGetSzParam(szCommand, "name", sz, sizeof(sz)))
  2363.     {
  2364.         strcpy_s(szResponse, cchResponse, "missing name");
  2365.         return E_FAIL;
  2366.     }
  2367.  
  2368.     if(!FGetNamedDwParam(szCommand, "length", &pdmcd->cch, szResponse))
  2369.         return E_FAIL;
  2370.  
  2371.     liSize.HighPart = 0;
  2372.     liSize.LowPart = pdmcd->cch;
  2373.  
  2374.     st = FCreateFile(&pdmcd->h, GENERIC_WRITE | DELETE | SYNCHRONIZE,
  2375.         sz, &liSize, 0, 0, FILE_OVERWRITE_IF,
  2376.         FILE_SYNCHRONOUS_IO_NONALERT);
  2377.  
  2378.     if(FAILED(st))
  2379.         return XBDM_CANNOTCREATE;
  2380.  
  2381.     st = NtSetInformationFile(pdmcd->h, &iosb, &liSize, sizeof(liSize), FileEndOfFileInformation);
  2382.  
  2383.     if(FAILED(st))
  2384.     {
  2385.         fdi.DeleteFile = TRUE;
  2386.         NtSetInformationFile(pdmcd->h, &iosb, &fdi, sizeof(fdi), FileDispositionInformation);
  2387.         NtClose(pdmcd->h);
  2388.  
  2389.         return XBDM_DEVICEFULL;
  2390.     }
  2391.  
  2392.     pdmcc->BufferSize = 0x4000;
  2393.     pdmcc->Buffer = DmAllocatePoolWithTag(pdmcc->BufferSize, 'bdbd');
  2394.  
  2395.     if(pdmcc->Buffer == NULL)
  2396.     {
  2397.         fdi.DeleteFile = TRUE;
  2398.         NtSetInformationFile(pdmcd->h, &iosb, &fdi, sizeof(fdi), FileDispositionInformation);
  2399.         NtClose(pdmcd->h);
  2400.        
  2401.         return E_OUTOFMEMORY;
  2402.     }
  2403.  
  2404.     pdmcd->cchBuf = pdmcc->BufferSize;
  2405.     pdmcd->cch = 0;
  2406.     pdmcc->HandlingFunction = HrRecieveFileData;
  2407.     pdmcd->ib = 0;
  2408.     pdmcd->rgb = (LPSTR)pdmcc->Buffer;
  2409.     pdmcd->fError = FALSE;
  2410.  
  2411.     pdmcc->BytesRemaining = liSize.LowPart;
  2412.  
  2413.     return XBDM_READYFORBIN;
  2414. }
  2415.  
  2416. DMHRAPI HrRecieveVolumeFileData(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  2417. {
  2418.     // We act under the assumption that if the buffer is big enough, we get exactly however
  2419.     // many bytes we asked for in BytesRemaining, otherwise we just get a full buffer
  2420.  
  2421.     FILE_DISPOSITION_INFORMATION fdi;
  2422.     IO_STATUS_BLOCK iosb;
  2423.  
  2424. #define st ((DWORD*)(pdmcd->rgb + 0x4000))[pdmcd->vfile.remain]
  2425.  
  2426.     if(pdmcd->vfile.step != 3 && !pdmcc->DataSize)
  2427.     {
  2428.         // We lost the connection...
  2429.         if(pdmcd->h != INVALID_HANDLE_VALUE)
  2430.         {
  2431.             fdi.DeleteFile = TRUE;
  2432.             NtSetInformationFile(pdmcd->h, &iosb, &fdi, sizeof(fdi), FileDispositionInformation);
  2433.  
  2434.             NtClose(pdmcd->h);
  2435.             pdmcd->h = INVALID_HANDLE_VALUE;
  2436.         }
  2437.  
  2438.         DmFreePool(pdmcd->rgb);
  2439.         pdmcc->BytesRemaining = 0;
  2440.  
  2441.         return XBDM_ENDOFLIST;
  2442.     }
  2443.     else if(pdmcd->vfile.step == 0)
  2444.     {
  2445.         // Recieved file info block
  2446. #pragma pack(1)
  2447.         typedef struct
  2448.         {
  2449.             DWORD dwSize;
  2450.             ULONGLONG CreateTime;
  2451.             ULONGLONG ChangeTime;
  2452.             ULONGLONG FileSize;
  2453.             DWORD FileAttributes;
  2454.         } *__info;
  2455.  
  2456.         __info fInfo = (__info)pdmcc->Buffer;
  2457.  
  2458.         pdmcd->vfile.ChangeTime.QuadPart = fInfo->ChangeTime;
  2459.         pdmcd->vfile.CreationTime.QuadPart = fInfo->CreateTime;
  2460.         pdmcd->vfile.FileAttributes = fInfo->FileAttributes;
  2461.         pdmcd->vfile.FileSize = (DWORD)fInfo->FileSize;
  2462.        
  2463.         if(fInfo->FileSize > 0xFFFFFFFF)
  2464.              st = E_FAIL; // File too big
  2465.         else
  2466.             st = STATUS_SUCCESS;
  2467.  
  2468.         pdmcc->BytesRemaining = fInfo->dwSize - 0x20;
  2469.         pdmcd->ib = 0;
  2470.  
  2471.         pdmcd->vfile.step++;
  2472.     }
  2473.     else if(pdmcd->vfile.step == 1)
  2474.     {
  2475.         // Recieved file name
  2476.         LARGE_INTEGER li;
  2477.  
  2478.         if(NT_SUCCESS(st))
  2479.         {
  2480.             li.HighPart = 0;
  2481.             li.LowPart = pdmcd->vfile.FileSize;
  2482.  
  2483.             st = FCreateFile(&pdmcd->h, GENERIC_WRITE | DELETE | SYNCHRONIZE,
  2484.                 (char*)pdmcc->Buffer, &li, 0, 0, FILE_OVERWRITE_IF,
  2485.                 FILE_SYNCHRONOUS_IO_NONALERT);
  2486.         }
  2487.  
  2488.         pdmcc->BytesRemaining = pdmcd->vfile.FileSize;
  2489.         pdmcd->vfile.step++;
  2490.     }
  2491.     else if(pdmcd->vfile.step == 2)
  2492.     {
  2493.         // Recieved file data
  2494.         pdmcd->ib += pdmcc->DataSize;
  2495.         pdmcc->BytesRemaining -= pdmcc->DataSize;
  2496.  
  2497.         if((pdmcc->BytesRemaining == 0) || (pdmcd->ib == 0x4000))
  2498.         {
  2499.             // Write to file
  2500.             if((pdmcd->h != INVALID_HANDLE_VALUE) && NT_SUCCESS(st))
  2501.             {
  2502.                 st = NtWriteFile(pdmcd->h, NULL, NULL, NULL, &iosb, pdmcd->rgb, pdmcd->ib, NULL);
  2503.                 if(FAILED(st))
  2504.                 {
  2505.                     fdi.DeleteFile = TRUE;
  2506.                     NtSetInformationFile(pdmcd->h, &iosb, &fdi, sizeof(fdi), FileDispositionInformation);
  2507.                     NtClose(pdmcd->h);
  2508.                     pdmcd->h = INVALID_HANDLE_VALUE;
  2509.                 }
  2510.  
  2511.                 // Reset back to the start
  2512.                 pdmcd->ib = 0;
  2513.             }
  2514.         }
  2515.  
  2516.         if(pdmcc->BytesRemaining == 0)
  2517.         {
  2518.             pdmcd->vfile.remain++;
  2519.            
  2520.             if(pdmcd->h != INVALID_HANDLE_VALUE)
  2521.             {
  2522.                 NtClose(pdmcd->h);
  2523.                 pdmcd->h = INVALID_HANDLE_VALUE;
  2524.             }
  2525.  
  2526.             if(pdmcd->vfile.remain == pdmcd->cch)
  2527.             {
  2528.                 pdmcd->vfile.step++;
  2529.                 return XBDM_BINRESPONSE;
  2530.             }
  2531.             else
  2532.             {
  2533.                 pdmcd->vfile.step = 0;
  2534.                 pdmcc->BytesRemaining = 0x20;
  2535.  
  2536.                 pdmcd->ib = 0;
  2537.             }
  2538.         }
  2539.     }
  2540.     else if(pdmcd->vfile.step == 3)
  2541.     {
  2542.         // Send back status codes
  2543.         pdmcc->Buffer = pdmcd->rgb + 0x4000;
  2544.         pdmcc->BytesRemaining = 1;
  2545.         pdmcc->DataSize = pdmcd->cchBuf - 0x4000;
  2546.  
  2547.         pdmcd->vfile.step++;
  2548.     }
  2549.     else if(pdmcd->vfile.step == 4)
  2550.     {
  2551.         DmFreePool(pdmcd->rgb);
  2552.  
  2553.         return XBDM_ENDOFLIST; // Signal completion
  2554.     }
  2555.  
  2556.     // Fix up the values
  2557.     if(pdmcd->vfile.step != 4)
  2558.     {
  2559.         pdmcc->Buffer = pdmcd->rgb + pdmcd->ib;
  2560.         pdmcc->BufferSize = 0x4000 - pdmcd->ib;
  2561.     }
  2562.  
  2563. #undef st
  2564.  
  2565.     return XBDM_NOERR;
  2566. }
  2567.  
  2568. DMHRAPI HrSendVolumeFile(LPCSTR szCommand, LPSTR szResponse,
  2569.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2570. {
  2571.     if(!pdmcc)
  2572.         return E_FAIL;
  2573.  
  2574.     if(!FGetNamedDwParam(szCommand, "count", &pdmcd->cch, szResponse))
  2575.         return E_FAIL;
  2576.  
  2577.     pdmcc->BufferSize = 0x4000 + pdmcd->cch * 4;
  2578.     pdmcc->Buffer = DmAllocatePoolWithTag(pdmcc->BufferSize, 'bdbd');
  2579.  
  2580.     if(!pdmcc->Buffer)
  2581.         return E_OUTOFMEMORY;
  2582.  
  2583.     ZeroMemory(pdmcc->Buffer, pdmcc->BufferSize);
  2584.  
  2585.     pdmcd->rgb = (char*)pdmcc->Buffer;
  2586.  
  2587.     pdmcc->HandlingFunction = HrRecieveVolumeFileData;
  2588.     pdmcc->BytesRemaining = 0x20;
  2589.  
  2590.     pdmcd->cchBuf = pdmcc->BufferSize;
  2591.     pdmcd->vfile.remain = 0;
  2592.     pdmcd->vfile.step = 0;
  2593.     pdmcd->h = INVALID_HANDLE_VALUE;
  2594.  
  2595.     return XBDM_READYFORBIN;
  2596. }
  2597.  
  2598. DMHRAPI HrHwInfo(LPCSTR szCommand, LPSTR szResponse,
  2599.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2600. {
  2601.     if(!pdmcc)
  2602.         return E_FAIL;
  2603.  
  2604.     RtlSnprintf(szResponse, cchResponse,
  2605.         "Hardware Info Follows\r\n"
  2606.         "Flags              : 0x%08x\r\n"
  2607.         "NumberOfProcessors : 0x%02x\r\n"
  2608.         "PCIBridgeRevisionID: 0x%02x\r\n"
  2609.         "Reserved Bytes     : 0x %02x %02x %02x %02x %02x %02x\r\n"
  2610.         "BldrMagic          : 0x%04x\r\n"
  2611.         "BldrFlags          : 0x%04x\r\n"
  2612.         ".",
  2613.         XboxHardwareInfo->Flags, XboxHardwareInfo->NumberOfProcessors,
  2614.         XboxHardwareInfo->PCIBridgeRevisionID,
  2615.         XboxHardwareInfo->Reserved[0], XboxHardwareInfo->Reserved[1],
  2616.         XboxHardwareInfo->Reserved[2], XboxHardwareInfo->Reserved[3],
  2617.         XboxHardwareInfo->Reserved[4], XboxHardwareInfo->Reserved[5],
  2618.         XboxHardwareInfo->BldrMagic, XboxHardwareInfo->BldrFlags);
  2619.  
  2620.     return XBDM_NOERR;
  2621. }
  2622.  
  2623. DMHRAPI HrObjList(LPCSTR szCommand, LPSTR szResponse,
  2624.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2625. {
  2626.     PDMCONN pdmc;
  2627.  
  2628.     if(!pdmcc)
  2629.         return E_FAIL;
  2630.  
  2631.     pdmc = CONTAINING_RECORD(pdmcc, DMCONN, dmcc);
  2632.  
  2633.     DumpAllObjects("\\", pdmc->s);
  2634.  
  2635.     return XBDM_NOERR;
  2636. }
  2637.  
  2638. DMHRAPI HrSetDumpMode(LPCSTR szCommand, LPSTR szResponse,
  2639.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2640. {
  2641.     int i;
  2642.  
  2643.     for(i = 0;i <= DM_DUMPMODE_DISABLED;i++)
  2644.     {
  2645.         if(PchGetParam(szCommand, rgszDumpMode[i], FALSE))
  2646.             break;
  2647.     }
  2648.  
  2649.     if(i > DM_DUMPMODE_DISABLED)
  2650.         return XBDM_NOERR;
  2651.  
  2652.     DmSetDumpMode(i);
  2653.  
  2654.     strcpy_s(szResponse, cchResponse, rgszDumpMode[i]);
  2655.     return XBDM_NOERR;
  2656. }
  2657.  
  2658. DMHRAPI HrNotify(LPCSTR szCommand, LPSTR szResponse,
  2659.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2660. {
  2661.     DWORD dwPort;
  2662.     PDMCONN conn;
  2663.  
  2664.     if(!FGetNamedDwParam(szCommand, "reconnectport", &dwPort, szResponse))
  2665.         return E_FAIL;
  2666.  
  2667.     conn = CONTAINING_RECORD(pdmcc, DMCONN, dmcc);
  2668.  
  2669.     FConvertToNotifySock(conn, dwPort);
  2670.  
  2671.     return XBDM_NOERR;
  2672. }
  2673.  
  2674. DMHRAPI HrNotifyAt(LPCSTR szCommand, LPSTR szResponse,
  2675.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2676. {
  2677.     DWORD dw;
  2678.  
  2679.     if(!FGetNamedDwParam(szCommand, "port", &dw, szResponse))
  2680.         return E_FAIL;
  2681.     if(!PchGetParam(szCommand, "drop", FALSE))
  2682.         return E_FAIL;
  2683.  
  2684.     return FDropNotifySock(dw);
  2685. }
  2686.  
  2687. DMHRAPI HrAttachDebugger(LPCSTR szCommand, LPSTR szResponse,
  2688.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2689. {
  2690.     DWORD dwPort;
  2691.     BOOL fOverride;
  2692.  
  2693.     fOverride = (BOOL)PchGetParam(szCommand, "override", FALSE);
  2694.  
  2695.     if(PchGetParam(szCommand, "connect", FALSE))
  2696.     {
  2697.         if(g_dmGlobals.bDebugging && !fOverride)
  2698.             return XBDM_ALREADYEXISTS;
  2699.  
  2700.         g_dmGlobals.dwDebugPort = 0;
  2701.         ZeroMemory(g_dmGlobals.rgchDebuggerName, sizeof(g_dmGlobals.rgchDebuggerName));
  2702.         ZeroMemory(g_dmGlobals.rgchDebuggerUser, sizeof(g_dmGlobals.rgchDebuggerUser));
  2703.  
  2704.         FGetDwParam(szCommand, "port", &g_dmGlobals.dwDebugPort);
  2705.         FGetSzParam(szCommand, "name", g_dmGlobals.rgchDebuggerName, sizeof(g_dmGlobals.rgchDebuggerName));
  2706.         FGetSzParam(szCommand, "user", g_dmGlobals.rgchDebuggerUser, sizeof(g_dmGlobals.rgchDebuggerUser));
  2707.  
  2708.         g_dmGlobals.bDebugging = TRUE;
  2709.     }
  2710.     else if(PchGetParam(szCommand, "disconnect", FALSE))
  2711.     {
  2712.         if((g_dmGlobals.dwDebugPort == 0)
  2713.             || (FGetDwParam(szCommand, "port", &dwPort) && dwPort == g_dmGlobals.dwDebugPort)
  2714.             || fOverride)
  2715.         {
  2716.             ZeroMemory(g_dmGlobals.rgchDebuggerName, sizeof(g_dmGlobals.rgchDebuggerName));
  2717.             ZeroMemory(g_dmGlobals.rgchDebuggerUser, sizeof(g_dmGlobals.rgchDebuggerUser));
  2718.             g_dmGlobals.bDebugging = FALSE;
  2719.         }
  2720.         else
  2721.             return XBDM_CANNOTACCESS;
  2722.     }
  2723.     else
  2724.     {
  2725.         strcpy_s(szResponse, cchResponse, "no command");
  2726.         return E_FAIL;
  2727.     }
  2728.  
  2729.     return XBDM_NOERR;
  2730. }
  2731.  
  2732. DMHRAPI HrIsDebuggerAttached(LPCSTR szCommand, LPSTR szResponse,
  2733.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2734. {
  2735.     const char *sz1, *sz2, *sz3, *sz4, *sz5, *sz6;
  2736.  
  2737.     if(!pdmcc)
  2738.         return E_FAIL;
  2739.  
  2740.     if(!g_dmGlobals.bDebugging)
  2741.         return XBDM_NOERR;
  2742.  
  2743.     if(g_dmGlobals.rgchDebuggerUser[0])
  2744.     {
  2745.         sz1 = "user=\"";
  2746.         sz2 = g_dmGlobals.rgchDebuggerUser;
  2747.         sz3 = "\"";
  2748.     }
  2749.     else
  2750.     {
  2751.         sz1 = "";
  2752.         sz2 = "";
  2753.         sz3 = "";
  2754.     }
  2755.  
  2756.     if(g_dmGlobals.rgchDebuggerName[0])
  2757.     {
  2758.         sz4 = "name=\"";
  2759.         sz5 = g_dmGlobals.rgchDebuggerName;
  2760.         sz6 = "\"";
  2761.     }
  2762.     else
  2763.     {
  2764.         sz4 = "";
  2765.         sz5 = "";
  2766.         sz6 = "";
  2767.     }
  2768.  
  2769.     RtlSnprintf(szResponse, cchResponse, "%s%s%s%s%s%s%s",
  2770.         sz1, sz2, sz3,
  2771.         (sz1[0] && sz4[0]) ? " " : "",
  2772.         sz4, sz5, sz6);
  2773.  
  2774.     return XBDM_ALREADYEXISTS;
  2775. }
  2776.  
  2777. DMHRAPI HrReportSystemInfo(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  2778. {
  2779.     char *sz;
  2780.  
  2781.     switch(pdmcc->BytesRemaining)
  2782.     {
  2783.     case 1:
  2784.         strcpy_s((char*)pdmcc->Buffer, pdmcc->BufferSize, "HDD=");
  2785.         if(XboxHardwareInfo->Flags & 0x20)
  2786.             strcat_s((char*)pdmcc->Buffer, pdmcc->BufferSize, "Enabled");
  2787.         else
  2788.             strcat_s((char*)pdmcc->Buffer, pdmcc->BufferSize, "Disabled");
  2789.         break;
  2790.     case 2:
  2791.         strcpy_s((char*)pdmcc->Buffer, pdmcc->BufferSize, "Type=");
  2792.         if(XboxHardwareInfo->Flags & 0x02000000)
  2793.             sz = "TestKit";
  2794.         else
  2795.             sz = "DevKit";
  2796.         strcat_s((char*)pdmcc->Buffer, pdmcc->BufferSize, sz);
  2797.         break;
  2798.     case 3:
  2799.         strcpy_s((char*)pdmcc->Buffer, pdmcc->BufferSize, "Platform=");
  2800.         switch(XboxHardwareInfo->Flags & 3)
  2801.         {
  2802.         case 0:
  2803.             sz = "Alpha";
  2804.             break;
  2805.         case 1:
  2806.             sz = "Mongrel";
  2807.             break;
  2808.         case 2:
  2809.             sz = "Shiva";
  2810.             break;
  2811.         case 3:
  2812.             sz = "Waternoose";
  2813.             break;
  2814.         default:
  2815.             sz = "Unknown";
  2816.             break;
  2817.         }
  2818.         strcat_s((char*)pdmcc->Buffer, pdmcc->BufferSize, sz);
  2819.         strcat_s((char*)pdmcc->Buffer, pdmcc->BufferSize, " System=");
  2820.         switch((XboxHardwareInfo->Flags >> 28) & 0xF)
  2821.         {
  2822.         case 0:
  2823.             sz = "Xenon";
  2824.             break;
  2825.         case 1:
  2826.             sz = "Zephyr";
  2827.             break;
  2828.         case 2:
  2829.             sz = "Falcon";
  2830.             break;
  2831.         case 3:
  2832.             sz = "Jasper";
  2833.             break;
  2834.         case 4:
  2835.             sz = "Trinity";
  2836.             break;
  2837.         case 5:
  2838.             sz = "Corona";
  2839.             break;
  2840.         case 6:
  2841.             sz = "Winchester";
  2842.             break;
  2843.         default:
  2844.             sz = "Unknown";
  2845.             break;
  2846.         }
  2847.         strcat_s((char*)pdmcc->Buffer, pdmcc->BufferSize, sz);
  2848.         break;
  2849.     case 4:
  2850.         RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "BaseKrnl=%d.%d.%d.%d Krnl=%d.%d.%d.%d XDK=2.0.20353.0",
  2851.             XboxKrnlBaseVersion->Major, XboxKrnlBaseVersion->Minor, XboxKrnlBaseVersion->Build,
  2852.             (XboxKrnlBaseVersion->ApprovalType << 8) + XboxKrnlBaseVersion->QFE,
  2853.             XboxKrnlVersion->Major, XboxKrnlVersion->Minor, XboxKrnlVersion->Build,
  2854.             (XboxKrnlVersion->ApprovalType << 8) + XboxKrnlVersion->QFE);
  2855.         break;
  2856.     case 5:
  2857.         return XBDM_ENDOFLIST;
  2858.     }
  2859.  
  2860.     pdmcc->BytesRemaining++;
  2861.  
  2862.     return XBDM_NOERR;
  2863. }
  2864.  
  2865. DMHRAPI HrGetSystemInfo(LPCSTR szCommand, LPSTR szResponse,
  2866.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2867. {
  2868.     if(!pdmcc)
  2869.         return E_FAIL;
  2870.  
  2871.     pdmcc->HandlingFunction = HrReportSystemInfo;
  2872.     pdmcc->BytesRemaining = 1;
  2873.  
  2874.     return XBDM_MULTIRESPONSE;
  2875. }
  2876.  
  2877. VOID PcregNext(DMCR* Context)
  2878. {
  2879.     for(;;)
  2880.     {
  2881.         if(Context->CurrentRegister == cchregs)
  2882.         {
  2883.             Context->CurrentRegister = 0;
  2884.             Context->Register = NULL;
  2885.             return;
  2886.         }
  2887.  
  2888.         Context->Register = &rgbregs[Context->CurrentRegister];
  2889.         Context->CurrentRegister++;
  2890.  
  2891.         if(Context->Context.ContextFlags & Context->Register->Context)
  2892.             break;
  2893.     }
  2894. }
  2895.  
  2896. DMHRAPI HrReportContext(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  2897. {
  2898.     int i;
  2899.     DMCR *context = ((DMCR*)pdmcc->CustomData);
  2900.  
  2901.     if(!context->Register)
  2902.     {
  2903.         DmFreePool(pdmcc->CustomData);
  2904.         return XBDM_ENDOFLIST;
  2905.     }
  2906.  
  2907.     pdmcc->DataSize = 0;
  2908.     for(i = 0;i < 4;i++)
  2909.     {
  2910.         if(context->Register->Size == 4)
  2911.         {
  2912.             pdmcc->DataSize += RtlSprintf((char*)pdmcc->Buffer + pdmcc->DataSize, "%s=0x%08x\r\n",
  2913.                 context->Register->Name, *(LPDWORD)((char*)&context->Context + context->Register->Offset));
  2914.         }
  2915.         else if(context->Register->Size == 8)
  2916.         {
  2917.             pdmcc->DataSize += RtlSprintf((char*)pdmcc->Buffer + pdmcc->DataSize, "%s=0q%016I64x\r\n",
  2918.                 context->Register->Name, *(QWORD*)((char*)&context->Context + context->Register->Offset));
  2919.         }
  2920.         else if(context->Register->Size == 16)
  2921.         {
  2922.             pdmcc->DataSize += RtlSprintf((char*)pdmcc->Buffer + pdmcc->DataSize, "%s=0x%08x,0x%08x,0x%08x,0x%08x\r\n",
  2923.                 context->Register->Name,
  2924.                 (LPDWORD)((char*)&context->Context + context->Register->Offset)[0],
  2925.                 (LPDWORD)((char*)&context->Context + context->Register->Offset)[1],
  2926.                 (LPDWORD)((char*)&context->Context + context->Register->Offset)[2],
  2927.                 (LPDWORD)((char*)&context->Context + context->Register->Offset)[3]);
  2928.         }
  2929.  
  2930.         PcregNext(context);
  2931.  
  2932.         if(!context->Register)
  2933.             break;
  2934.     }
  2935.  
  2936.     return XBDM_NOERR;
  2937. }
  2938.  
  2939. DMHRAPI HrGetContext(LPCSTR szCommand, LPSTR szResponse,
  2940.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2941. {
  2942.     XCONTEXT context;
  2943.     DWORD dwThreadId;
  2944.     HRESULT hr;
  2945.  
  2946.     if(!pdmcc)
  2947.         return E_FAIL;
  2948.  
  2949.     if(!FGetNamedDwParam(szCommand, "thread", &dwThreadId, szResponse))
  2950.         return E_FAIL;
  2951.  
  2952.     context.ContextFlags = 0;
  2953.     if(PchGetParam(szCommand, "control", FALSE))
  2954.         context.ContextFlags |= CONTEXT_CONTROL;
  2955.     if(PchGetParam(szCommand, "int", FALSE))
  2956.         context.ContextFlags |= CONTEXT_INTEGER;
  2957.     if(PchGetParam(szCommand, "fp", FALSE))
  2958.         context.ContextFlags |= CONTEXT_FLOATING_POINT;
  2959.     if(PchGetParam(szCommand, "vr", FALSE))
  2960.         context.ContextFlags |= CONTEXT_VECTOR;
  2961.     if(PchGetParam(szCommand, "full", FALSE))
  2962.         context.ContextFlags |= CONTEXT_FULL;
  2963.  
  2964.     hr = DmGetThreadContext(dwThreadId, &context);
  2965.  
  2966.     if(FAILED(hr))
  2967.         return hr;
  2968.  
  2969.     pdmcc->CustomData = DmAllocatePoolWithTag(sizeof(DMCR), 'dmcr');
  2970.    
  2971.     if(!pdmcc->CustomData)
  2972.         return E_OUTOFMEMORY;
  2973.  
  2974.     ((DMCR*)pdmcc->CustomData)->CurrentRegister = 0;
  2975.     ((DMCR*)pdmcc->CustomData)->Register = NULL;
  2976.     memcpy(pdmcc->CustomData, &context, sizeof(XCONTEXT));
  2977.  
  2978.     PcregNext(((DMCR*)pdmcc->CustomData));
  2979.     pdmcc->HandlingFunction = HrReportContext;
  2980.  
  2981.     return XBDM_MULTIRESPONSE;
  2982. }
  2983.  
  2984. DMHRAPI HrSetContext(LPCSTR szCommand, LPSTR szResponse,
  2985.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  2986. {
  2987.     DMCR dmcr;
  2988.     DWORD dwThreadId;
  2989.     HRESULT hr;
  2990.     BOOL bCopy;
  2991.  
  2992.     char sz[0x10];
  2993.  
  2994.     if(!pdmcc)
  2995.         return E_FAIL;
  2996.  
  2997.     if(!FGetNamedDwParam(szCommand, "thread", &dwThreadId, szResponse))
  2998.         return E_FAIL;
  2999.  
  3000.     ZeroMemory(&dmcr, sizeof(DMCR));
  3001.  
  3002.     dmcr.Context.ContextFlags = CONTEXT_FULL;
  3003.     dmcr.CurrentRegister = 0;
  3004.     dmcr.Register = NULL;
  3005.  
  3006.     hr = DmGetThreadContext(dwThreadId, &dmcr.Context);
  3007.  
  3008.     if(FAILED(hr))
  3009.         return hr;
  3010.  
  3011.     for(;;)
  3012.     {
  3013.         PcregNext(&dmcr);
  3014.  
  3015.         if(dmcr.Register == NULL)
  3016.             break;
  3017.  
  3018.         if(dmcr.Register->Size == 4)
  3019.             bCopy = FGetDwParam(szCommand, dmcr.Register->Name, (DWORD*)sz);
  3020.         else if(dmcr.Register->Size == 8)
  3021.             bCopy = FGetQwordParam(szCommand, dmcr.Register->Name, (ULARGE_INTEGER*)sz);
  3022.         else if(dmcr.Register->Size == 0x10)
  3023.             bCopy = FGetVectorParam(szCommand, dmcr.Register->Name, (float*)sz);
  3024.         else
  3025.             bCopy = FALSE;
  3026.  
  3027.         if(bCopy)
  3028.             memcpy((char*)&dmcr.Context + dmcr.Register->Offset, sz, dmcr.Register->Size);
  3029.     }
  3030.  
  3031.     hr = DmSetThreadContext(dwThreadId, &dmcr.Context);
  3032.  
  3033.     return hr;
  3034. }
  3035.  
  3036. DMHRAPI HrReportThreadList(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  3037. {
  3038.     if(pdmcd->cch == pdmcd->ib)
  3039.     {
  3040.         DmFreePool(pdmcd->rgb);
  3041.         return XBDM_ENDOFLIST;
  3042.     }
  3043.  
  3044.     pdmcc->DataSize = 0;
  3045.  
  3046.     while((pdmcc->DataSize + 0x10 < pdmcc->BufferSize)
  3047.         && (pdmcd->cch != pdmcd->ib))
  3048.     {
  3049.         pdmcc->DataSize += RtlSprintf((char*)pdmcc->Buffer + pdmcc->DataSize, "%d\r\n", ((LPDWORD)pdmcd->rgb)[pdmcd->ib]);
  3050.         pdmcd->ib++;
  3051.     }
  3052.     return XBDM_NOERR;
  3053. }
  3054.  
  3055. DMHRAPI HrListThreads(LPCSTR szCommand, LPSTR szResponse,
  3056.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3057. {
  3058.     HRESULT hr;
  3059.  
  3060.     if(!pdmcc)
  3061.         return E_FAIL;
  3062.  
  3063.     pdmcd->rgb = (char*)DmAllocatePoolWithTag(0x400, 'xbdm');
  3064.     pdmcd->cch = 0x100;
  3065.    
  3066.     if(!pdmcd->rgb)
  3067.         return E_OUTOFMEMORY;
  3068.  
  3069.     hr = DmGetThreadList((LPDWORD)pdmcd->rgb, &pdmcd->cch);
  3070.  
  3071.     if(FAILED(hr))
  3072.     {
  3073.         if(hr == XBDM_BUFFER_TOO_SMALL)
  3074.             hr = E_UNEXPECTED;
  3075.  
  3076.         DmFreePool(pdmcd->rgb);
  3077.     }
  3078.     else
  3079.     {
  3080.         hr = XBDM_MULTIRESPONSE;
  3081.         strcpy_s(szResponse, cchResponse, "thread list follows");
  3082.  
  3083.         pdmcc->HandlingFunction = HrReportThreadList;
  3084.         pdmcd->ib = 0;
  3085.     }
  3086.  
  3087.     return hr;
  3088. }
  3089.  
  3090. DMHRAPI HrReportThreadListEx(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  3091. {
  3092.     if(pdmcd->cch == pdmcd->ib)
  3093.     {
  3094.         DmFreePool(pdmcd->rgb);
  3095.         return XBDM_ENDOFLIST;
  3096.     }
  3097.  
  3098.     pdmcc->DataSize = 0;
  3099.  
  3100.     while((pdmcc->DataSize + 0x10 < pdmcc->BufferSize)
  3101.         && (pdmcd->cch != pdmcd->ib))
  3102.     {
  3103.         pdmcc->DataSize += RtlSprintf((char*)pdmcc->Buffer + pdmcc->DataSize, "%08X\r\n", ((LPDWORD)pdmcd->rgb)[pdmcd->ib]);
  3104.         pdmcd->ib++;
  3105.     }
  3106.     return XBDM_NOERR;
  3107. }
  3108.  
  3109. DMHRAPI HrListThreadsEx(LPCSTR szCommand, LPSTR szResponse,
  3110.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3111. {
  3112.     HRESULT hr;
  3113.  
  3114.     if(!pdmcc)
  3115.         return E_FAIL;
  3116.  
  3117.     pdmcd->rgb = (char*)DmAllocatePoolWithTag(0x400, 'xbdm');
  3118.     pdmcd->cch = 0x100;
  3119.    
  3120.     if(!pdmcd->rgb)
  3121.         return E_OUTOFMEMORY;
  3122.  
  3123.     hr = DmGetThreadList((LPDWORD)pdmcd->rgb, &pdmcd->cch);
  3124.  
  3125.     if(FAILED(hr))
  3126.     {
  3127.         if(hr == XBDM_BUFFER_TOO_SMALL)
  3128.             hr = E_UNEXPECTED;
  3129.  
  3130.         DmFreePool(pdmcd->rgb);
  3131.     }
  3132.     else
  3133.     {
  3134.         hr = XBDM_MULTIRESPONSE;
  3135.         strcpy_s(szResponse, cchResponse, "thread list follows");
  3136.  
  3137.         pdmcc->HandlingFunction = HrReportThreadListEx;
  3138.         pdmcd->ib = 0;
  3139.     }
  3140.  
  3141.     return hr;
  3142. }
  3143.  
  3144. DMHRAPI HrGetCpuKey(LPCSTR szCommand, LPSTR szResponse,
  3145.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3146. {
  3147.     QWORD fuses[12];
  3148.  
  3149.     HvGetFuses(fuses);
  3150.  
  3151.     RtlSnprintf(szResponse, cchResponse, "%016I64X%016I64X", fuses[3], fuses[5]);
  3152.     return XBDM_NOERR;
  3153. }
  3154.  
  3155. DMHRAPI HrContinueThread(LPCSTR szCommand, LPSTR szResponse,
  3156.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3157. {
  3158.     DWORD dwThreadId;
  3159.  
  3160.     if(!FGetNamedDwParam(szCommand, "thread", &dwThreadId, szResponse))
  3161.         return E_FAIL;
  3162.  
  3163.     return DmContinueThread(dwThreadId, (BOOL)PchGetParam(szCommand, "exception", FALSE));
  3164. }
  3165.  
  3166. DMHRAPI HrDoStopOn(LPCSTR szCommand, LPSTR szResponse,
  3167.     DWORD cchResponse, BOOL fStop)
  3168. {
  3169.     DWORD dw = 0;
  3170.  
  3171.     if(PchGetParam(szCommand, "all", FALSE))
  3172.         dw = -1;
  3173.     else
  3174.     {
  3175.         if(PchGetParam(szCommand, "fce", FALSE))
  3176.             dw |= DMSTOP_FCE;
  3177.         if(PchGetParam(szCommand, "debugstr", FALSE))
  3178.             dw |= DMSTOP_DEBUGSTR;
  3179.         if(PchGetParam(szCommand, "createthread", FALSE))
  3180.             dw |= DMSTOP_CREATETHREAD;
  3181.         if(PchGetParam(szCommand, "stacktrace", FALSE))
  3182.             dw |= DMSTOP_STACKTRACE;
  3183.         if(PchGetParam(szCommand, "modload", FALSE))
  3184.             dw |= DMSTOP_MODLOAD;
  3185.     }
  3186.  
  3187.     return DmStopOn(dw, fStop);
  3188. }
  3189.  
  3190. DMHRAPI HrStopOn(LPCSTR szCommand, LPSTR szResponse,
  3191.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3192. {
  3193.     return HrDoStopOn(szCommand, szResponse, cchResponse, TRUE);
  3194. }
  3195.  
  3196. DMHRAPI HrNoStopOn(LPCSTR szCommand, LPSTR szResponse,
  3197.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3198. {
  3199.     return HrDoStopOn(szCommand, szResponse, cchResponse, FALSE);
  3200. }
  3201.  
  3202. DMHRAPI HrIsThreadStopped(LPCSTR szCommand, LPSTR szResponse,
  3203.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3204. {
  3205.     DM_THREADSTOP dmts;
  3206.     DWORD dwThreadId;
  3207.     HRESULT hr;
  3208.  
  3209.     if(!pdmcc)
  3210.         return E_FAIL;
  3211.  
  3212.     if(!FGetNamedDwParam(szCommand, "thread", &dwThreadId, szResponse))
  3213.         return E_FAIL;
  3214.  
  3215.     hr = DmIsThreadStopped(dwThreadId, &dmts);
  3216.  
  3217.     if(FAILED(hr))
  3218.         return hr;
  3219.  
  3220.     if(dmts.NotifiedReason == DM_ASSERT)
  3221.         RtlSnprintf(szResponse, cchResponse, "assert thread=0x%08x straddr=0x%08x strlen=0x%08x",
  3222.         dmts.u.DebugStr.ThreadId, dmts.u.DebugStr.String, dmts.u.DebugStr.Length);
  3223.     else if(dmts.NotifiedReason == DM_DEBUGSTR)
  3224.         RtlSnprintf(szResponse, cchResponse, "debugstr thread=0x%08x stop", dmts.u.DebugStr.ThreadId);
  3225.     else if(!FGetNotifySz(dmts.NotifiedReason, (ULONG_PTR)&dmts.u, szResponse, cchResponse))
  3226.         strcpy_s(szResponse, cchResponse, "stopped");
  3227.  
  3228.     return XBDM_NOERR;
  3229. }
  3230.  
  3231. DMHRAPI HrSuspendThread(LPCSTR szCommand, LPSTR szResponse,
  3232.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3233. {
  3234.     DWORD dwThreadId;
  3235.  
  3236.     if(!pdmcc)
  3237.         return E_FAIL;
  3238.  
  3239.     if(!FGetNamedDwParam(szCommand, "thread", &dwThreadId, szResponse))
  3240.         return FALSE;
  3241.  
  3242.     return DmSuspendThread(dwThreadId);
  3243. }
  3244.  
  3245. DMHRAPI HrResumeThread(LPCSTR szCommand, LPSTR szResponse,
  3246.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3247. {
  3248.     DWORD dwThreadId;
  3249.  
  3250.     if(!pdmcc)
  3251.         return E_FAIL;
  3252.  
  3253.     if(!FGetNamedDwParam(szCommand, "thread", &dwThreadId, szResponse))
  3254.         return FALSE;
  3255.  
  3256.     return DmResumeThread(dwThreadId);
  3257. }
  3258.  
  3259. DMHRAPI HrReportThreadInfo(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  3260. {
  3261.     if(pdmcc->BytesRemaining == 2)
  3262.         return XBDM_ENDOFLIST;
  3263.  
  3264.     pdmcc->BytesRemaining++;
  3265.  
  3266.     RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize,
  3267.         "suspend=%d priority=%d tlsbase=0x%08x start=0x%08x base=0x%08x limit=0x%08x slack=0x%08x createhi=0x%08x createlo=0x%08x nameaddr=0x%08x namelen=0x%08x proc=0x%02X lasterr=0x%08x",
  3268.         pdmcd->dmti.SuspendCount, pdmcd->dmti.Priority, pdmcd->dmti.TlsBase, pdmcd->dmti.StartAddress,
  3269.         pdmcd->dmti.StackBase, pdmcd->dmti.StackLimit, pdmcd->dmti.StackSlackSpace, pdmcd->dmti.CreateTime.dwHighDateTime,
  3270.         pdmcd->dmti.CreateTime.dwLowDateTime, pdmcd->dmti.ThreadNameAddress,
  3271.         pdmcd->dmti.ThreadNameLength, pdmcd->dmti.CurrentProcessor, pdmcd->dmti.LastError);
  3272.  
  3273.     return XBDM_NOERR;
  3274. }
  3275.  
  3276. DMHRAPI HrGetThreadInfo(LPCSTR szCommand, LPSTR szResponse,
  3277.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3278. {
  3279.     DWORD dwThreadId;
  3280.     HRESULT hr;
  3281.  
  3282.     if(!pdmcc)
  3283.         return E_FAIL;
  3284.  
  3285.     if(!FGetNamedDwParam(szCommand, "thread", &dwThreadId, szResponse))
  3286.         return FALSE;
  3287.  
  3288.     pdmcd->dmti.Size = sizeof(DM_THREADINFOEX);
  3289.     hr = DmGetThreadInfoEx(dwThreadId, &pdmcd->dmti);
  3290.  
  3291.     if(FAILED(hr))
  3292.         return hr;
  3293.  
  3294.     pdmcc->HandlingFunction = HrReportThreadInfo;
  3295.     pdmcc->BytesRemaining = 1;
  3296.  
  3297.     strcpy_s(szResponse, cchResponse, "thread info follows");
  3298.  
  3299.     return XBDM_MULTIRESPONSE;
  3300. }
  3301.  
  3302. DMHRAPI HrReportModuleSections(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  3303. {
  3304.     if(pdmcc->BytesRemaining == 3)
  3305.         return XBDM_ENDOFLIST;
  3306.  
  3307.     RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "name=\"%s\" base=0x%08x size=0x%08x index=%d flags=%d",
  3308.         pdmcd->dmsl.Name, pdmcd->dmsl.BaseAddress, pdmcd->dmsl.Size, pdmcd->dmsl.Index, pdmcd->dmsl.Flags);
  3309.  
  3310.     if(pdmcc->BytesRemaining == 2)
  3311.         pdmcc->BytesRemaining++;
  3312.     else if(FAILED(DmWalkModuleSections((PDM_WALK_MODSECT*)&pdmcd->rgb, pdmcd->sz, &pdmcd->dmsl)))
  3313.     {
  3314.         pdmcc->BytesRemaining++;
  3315.         DmCloseModuleSections((PDM_WALK_MODSECT)pdmcd->rgb);
  3316.     }
  3317.  
  3318.     return XBDM_NOERR;
  3319. }
  3320.  
  3321. DMHRAPI HrListModuleSections(LPCSTR szCommand, LPSTR szResponse,
  3322.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3323. {
  3324.     if(!pdmcc)
  3325.         return E_FAIL;
  3326.  
  3327.     if(!FGetSzParam(szCommand, "name", pdmcd->sz, sizeof(pdmcd->sz)))
  3328.     {
  3329.         strcpy_s(szResponse, cchResponse, "missing name");
  3330.         return E_FAIL;
  3331.     }
  3332.  
  3333.     pdmcd->rgb = NULL;
  3334.     pdmcc->HandlingFunction = HrReportModuleSections;
  3335.     pdmcc->BytesRemaining = 1;
  3336.  
  3337.     if(NT_SUCCESS(DmWalkModuleSections((PDM_WALK_MODSECT*)&pdmcd->rgb, pdmcd->sz, &pdmcd->dmsl)))
  3338.         return XBDM_MULTIRESPONSE;
  3339.  
  3340.     return XBDM_NOSUCHFILE;
  3341. }
  3342.  
  3343. DMHRAPI HrGetProcessId(LPCSTR szCommand, LPSTR szResponse,
  3344.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3345. {
  3346.     ULARGE_INTEGER time;
  3347.  
  3348.     if(dwExecState == DMN_EXEC_PENDING)
  3349.         return XBDM_NOTHREAD;
  3350.  
  3351.     while(g_dmGlobals.dwPid == 0)
  3352.     {
  3353.         KeQuerySystemTime(&time);
  3354.         g_dmGlobals.dwPid = time.LowPart + __mftb32();
  3355.     }
  3356.  
  3357.     RtlSnprintf(szResponse, cchResponse, "pid=0x%08x", g_dmGlobals.dwPid);
  3358.  
  3359.     return XBDM_NOERR;
  3360. }
  3361.  
  3362. DMHRAPI HrReportXexField(PDM_CMDCONT pdmcc, LPSTR szResponse, DWORD cchResponse)
  3363. {
  3364.     if(pdmcc->BytesRemaining == 3)
  3365.         return XBDM_ENDOFLIST;
  3366.  
  3367.     if(pdmcc->BytesRemaining == 1)
  3368.     {
  3369.         pdmcc->BytesRemaining++;
  3370.         RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "fieldsize=0x%08x", 4);
  3371.     }
  3372.     else if(pdmcc->BytesRemaining == 2)
  3373.     {
  3374.         pdmcc->BytesRemaining++;
  3375.         RtlSnprintf((char*)pdmcc->Buffer, pdmcc->BufferSize, "%08X", (DWORD)pdmcd->rgb);
  3376.     }
  3377.  
  3378.     return XBDM_NOERR;
  3379. }
  3380.  
  3381. DMHRAPI HrGetXexField(LPCSTR szCommand, LPSTR szResponse,
  3382.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3383. {
  3384.     PLDR_DATA_TABLE_ENTRY pldte;
  3385.     char sz[MAX_PATH];
  3386.     DWORD dw;
  3387.     HRESULT hr;
  3388.  
  3389.     if(!pdmcc)
  3390.         return E_FAIL;
  3391.  
  3392.     if(!FGetSzParam(szCommand, "module", sz, sizeof(sz)))
  3393.     {
  3394.         strcpy_s(szResponse, cchResponse, "missing module");
  3395.         return E_FAIL;
  3396.     }
  3397.  
  3398.     if(!FGetNamedDwParam(szCommand, "field", &dw, szResponse))
  3399.         return E_FAIL;
  3400.  
  3401.     if(dw != 0x00010100)
  3402.     {
  3403.         DbgPrint("[xbdm] unknown command \"%s\"\n", szCommand);
  3404.         return XBDM_INVALIDCMD;
  3405.     }
  3406.  
  3407.     hr = FGetModuleHandle(sz, &pldte, TRUE);
  3408.  
  3409.     if(!pldte)
  3410.         return XBDM_NOSUCHFILE;
  3411.  
  3412.     pdmcd->rgb = (char*)RtlImageXexHeaderField(pldte->XexHeaderBase, dw);
  3413.     pdmcc->HandlingFunction = HrReportXexField;
  3414.     pdmcc->BytesRemaining = 1;
  3415.  
  3416.     if(pdmcd->rgb)
  3417.         return XBDM_MULTIRESPONSE;
  3418.     else
  3419.         return XBDM_FIELDNOTPRESENT;
  3420. }
  3421.  
  3422. DMHRAPI HrGetExecState(LPCSTR szCommand, LPSTR szResponse,
  3423.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3424. {
  3425.     char *sz;
  3426.  
  3427.     switch(dwExecState)
  3428.     {
  3429.     case DMN_EXEC_START:
  3430.         sz = "start";
  3431.         break;
  3432.     case DMN_EXEC_STOP:
  3433.         sz = "stop";
  3434.         break;
  3435.     case DMN_EXEC_PENDING:
  3436.         sz = "pending";
  3437.         break;
  3438.         case DMN_EXEC_REBOOT:
  3439.             sz = "reboot";
  3440.         break;
  3441.     case DMN_EXEC_PENDING_TITLE:
  3442.         sz = "pending_title";
  3443.         break;
  3444.     case DMN_EXEC_REBOOT_TITLE:
  3445.         sz = "reboot_title";
  3446.         break;
  3447.     }
  3448.  
  3449.     RtlSnprintf(szResponse, cchResponse, "%s", sz);
  3450.  
  3451.     return XBDM_NOERR;
  3452. }
  3453.  
  3454. DMHRAPI HrGetConsoleId(LPCSTR szCommand, LPSTR szResponse,
  3455.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3456. {
  3457.     char sz[0xD];
  3458.     NTSTATUS st;
  3459.  
  3460.     ZeroMemory(sz, sizeof(sz));
  3461.     st = XeKeysGetConsoleID(NULL, sz);
  3462.  
  3463.     if(FAILED(st))
  3464.         return (HRESULT)(st | 0x10000000);
  3465.    
  3466.     RtlSnprintf(szResponse, cchResponse, "consoleid=%s", sz);
  3467.     return XBDM_NOERR;
  3468. }
  3469.  
  3470. DMHRAPI HrBreak(LPCSTR szCommand, LPSTR szResponse,
  3471.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3472. {
  3473.     HRESULT hr = XBDM_NOERR;
  3474.     BOOL bClear;
  3475.     DWORD dwAddr;
  3476.     DWORD dwFlags;
  3477.     DWORD dwSize;
  3478.  
  3479.     if(PchGetParam(szCommand, "now", FALSE))
  3480.     {
  3481.         Sleep(250);
  3482.         __emit(BREAKPOINT_BREAK);
  3483.     }
  3484.     else if(PchGetParam(szCommand, "start", FALSE))
  3485.     {
  3486.         if(FAILED(hr = DmSetInitialBreakpoint()))
  3487.             strcpy_s(szResponse, cchResponse, "execution not pending");
  3488.     }
  3489.     else if(PchGetParam(szCommand, "clearall", FALSE))
  3490.         DmRemoveAllBreakpoints();
  3491.     else
  3492.     {
  3493.         bClear = (BOOL)PchGetParam(szCommand, "clear", FALSE);
  3494.         if(FGetNamedDwParam(szCommand, "addr", &dwAddr, szResponse))
  3495.         {
  3496.             if(bClear)
  3497.                 DmRemoveBreakpoint((PVOID)dwAddr);
  3498.             else
  3499.                 DmSetBreakpoint((PVOID)dwAddr);
  3500.         }
  3501.         else
  3502.         {
  3503.             if(FGetDwParam(szCommand, "read", &dwAddr))
  3504.                 dwFlags = DMBREAK_READ;
  3505.             else if(FGetDwParam(szCommand, "write", &dwAddr))
  3506.                 dwFlags = DMBREAK_WRITE;
  3507.             else if(FGetDwParam(szCommand, "readwrite", &dwAddr))
  3508.                 dwFlags = DMBREAK_READWRITE;
  3509.             else if(FGetDwParam(szCommand, "execute", &dwAddr))
  3510.                 dwFlags = DMBREAK_EXECUTE;
  3511.             else
  3512.                 hr = E_FAIL;
  3513.  
  3514.             if(NT_SUCCESS(hr))
  3515.             {
  3516.                 if(bClear)
  3517.                     dwFlags = DMBREAK_NONE;
  3518.                 else if(!FGetNamedDwParam(szCommand, "size", &dwSize, szResponse))
  3519.                     hr = E_FAIL;
  3520.  
  3521.                 if(NT_SUCCESS(hr))
  3522.                     DmSetDataBreakpoint((PVOID)dwAddr, dwFlags, dwSize);
  3523.             }
  3524.         }
  3525.     }
  3526.  
  3527.     if(NT_SUCCESS(hr))
  3528.         szResponse[0] = 0;
  3529.  
  3530.     return hr;
  3531. }
  3532.  
  3533. DMHRAPI HrGetDebuggerVersion(LPCSTR szCommand, LPSTR szResponse,
  3534.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3535. {
  3536.     strcpy_s(szResponse, cchResponse, "2.0.20353.0");
  3537.     return XBDM_NOERR;
  3538. }
  3539.  
  3540. DMHRAPI HrKhoungDm(LPCSTR szCommand, LPSTR szResponse,
  3541.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3542. {
  3543.     VdDisplayFatalError(69);
  3544.     return XBDM_NOERR;
  3545. }
  3546.  
  3547. DMHRAPI HrWhoMadeThis(LPCSTR szCommand, LPSTR szResponse,
  3548.     DWORD cchResponse, PDM_CMDCONT pdmcc)
  3549. {
  3550.     strcpy_s(szResponse, cchResponse, "Natelx did, of course");
  3551.     return XBDM_NOERR;
  3552. }
  3553.  
  3554. // Please keep in alphabetical order!
  3555. // And use these permission defines when adding commands!
  3556. /*
  3557. #define DMPL_PRIV_READ For reading from the console
  3558. #define DMPL_PRIV_WRITE For writing to the console (files)
  3559. #define DMPL_PRIV_CONTROL For controlling the console (must have this to do ANYTHING debug related!!!)
  3560. #define DMPL_PRIV_CONFIGURE For configuring the console
  3561. #define DMPL_PRIV_MANAGE For managing the console (must have this to edit accounts!!!)
  3562. #define DMPL_PRIV_HVX For ANYTHING that has to do with the hypervisor expansion(s)
  3563. */
  3564. DMCMD rgbcmd[] =
  3565. {
  3566.     { "altaddr",                DMPL_PRIV_READ,                     HrGetAltAddr            }, // Gets the title ip address
  3567.     { "break",                  DMPL_PRIV_CONTROL,                  HrBreak                 }, // Manages breakpoints
  3568.     { "bye",                    0,                                  HrEndConversation       }, // Ends the connection
  3569.     { "consolefeatures",        DMPL_PRIV_READ,                     HrGetConsoleFeatures    }, // Gets the console features (debug, ram)
  3570.     { "consoletype",            DMPL_PRIV_READ,                     HrGetConsoleType        }, // Gets the console type (test, dev)
  3571.     { "continue",               DMPL_PRIV_CONTROL,                  HrContinueThread        }, // Continues a thread
  3572.     { "dbgname",                DMPL_PRIV_READ,                     HrDbgName               }, // Gets the console name
  3573.     { "debugger",               DMPL_PRIV_CONTROL,                  HrAttachDebugger        }, // Signals that a debugger has been attached or deattached
  3574.     { "delete",                 DMPL_PRIV_WRITE,                    HrDelete                }, // Deletes a file or directory
  3575.     { "dirlist",                DMPL_PRIV_READ,                     HrGetDirList            }, // Gets a list of items in a folder
  3576.     { "dmversion",              DMPL_PRIV_CONTROL,                  HrGetDebuggerVersion    }, // Gets the debugger version
  3577.     { "drivefreespace",         DMPL_PRIV_READ,                     HrGetDriveFreeSpace     }, // Gets some stats about the drive's volume size
  3578.     { "drivelist",              DMPL_PRIV_READ,                     HrGetDriveList          }, // Gets the list of connected drives
  3579.     { "drivemap",               DMPL_PRIV_CONTROL,                  HrDrivemap              }, // Sets if FLASH:\\ is visible in the drive browser
  3580.     { "dumpmode",               DMPL_PRIV_CONFIGURE,                HrSetDumpMode           }, // Configures the crash dump mode
  3581.     { "dvdeject",               DMPL_PRIV_CONTROL,                  HrDvdEject              }, // Opens or closes the dvd tray
  3582.     { "getconsoleid",           DMPL_PRIV_CONTROL,                  HrGetConsoleId          }, // Gets the console id
  3583.     { "getcontext",             DMPL_PRIV_CONTROL,                  HrGetContext            }, // Gets a thread context
  3584.     { "getcpukey",              DMPL_PRIV_HVX,                      HrGetCpuKey             }, // Gets the cpu key
  3585.     { "getexecstate",           DMPL_PRIV_CONTROL,                  HrGetExecState          }, // Displays the execution state
  3586.     { "getfile",                DMPL_PRIV_READ,                     HrGetFile               }, // Xbox->PC transfer
  3587.     { "getfileattributes",      DMPL_PRIV_READ,                     HrGetFileAttr           }, // Gets file attributes
  3588.     { "getmem",                 DMPL_PRIV_CONTROL,                  HrGetMemory             }, // Gets memory
  3589.     { "getmemex",               DMPL_PRIV_CONTROL,                  HrGetMemoryEx           }, // Gets memory in data
  3590.     { "getpid",                 DMPL_PRIV_CONTROL,                  HrGetProcessId          }, // Gets the process id
  3591.     { "go",                     DMPL_PRIV_CONTROL,                  HrGo                    }, // Continues all threads
  3592.     { "help",                   0,                                  HrHelp                  }, // Gets info on every command
  3593.     { "hwinfo",                 0,                                  HrHwInfo                }, // Does some listing of stuff for cOz
  3594.     { "khoungdm",               DMPL_PRIV_CONTROL,                  HrKhoungDm              }, // E69
  3595.     { "isdebugger",             DMPL_PRIV_CONTROL,                  HrIsDebuggerAttached    }, // Gets info on the current debugger
  3596.     { "isstopped",              DMPL_PRIV_CONTROL,                  HrIsThreadStopped       }, // Returns information on a stopped thread
  3597.     { "magicboot",              DMPL_PRIV_CONTROL,                  HrMagicReboot           }, // Changes the currently running title, and/or reboots the console
  3598.     { "mkdir",                  DMPL_PRIV_WRITE,                    HrCreateDirectory       }, // Creates a folder
  3599.     { "modsections",            DMPL_PRIV_WRITE,                    HrListModuleSections    }, // Lists the module sections
  3600.     { "modules",                DMPL_PRIV_CONTROL,                  HrGetModules            }, // Returns a list of all the loaded modules (exe, dll)
  3601.     { "nostopon",               DMPL_PRIV_CONTROL,                  HrNoStopOn              }, // Changes what we stop on
  3602.     { "notify",                 DMPL_PRIV_CONTROL,                  HrNotify                }, // Creates a notification channel
  3603.     { "notifyat",               DMPL_PRIV_CONTROL,                  HrNotifyAt              }, // Manages a notification channel
  3604.     { "objlist",                0,                                  HrObjList               }, // Lists objects for cOz
  3605.     { "rename",                 DMPL_PRIV_WRITE,                    HrRenameFile            }, // Renames a file or directory
  3606.     { "resume",                 DMPL_PRIV_CONTROL,                  HrResumeThread          }, // Resumes a thread
  3607.     { "screenshot",             DMPL_PRIV_CONTROL,                  HrScreenshot            }, // Takes a screenshot
  3608.     { "sendfile",               DMPL_PRIV_WRITE,                    HrSendFile              }, // PC->Xbox transfer
  3609.     { "sendvfile",              DMPL_PRIV_WRITE,                    HrSendVolumeFile        }, // PC->Xbox transfer with several files
  3610.     { "setcolor",               DMPL_PRIV_CONTROL,                  HrSetColor              }, // Sets the color of the console in neighborhood
  3611.     { "setcontext",             DMPL_PRIV_CONTROL,                  HrSetContext            }, // Sets a thread context
  3612.     { "setfileattributes",      DMPL_PRIV_WRITE,                    HrSetFileAttr           }, // Sets file attributes
  3613.     { "setmem",                 DMPL_PRIV_CONTROL,                  HrSetMemory             }, // Sets memory
  3614.     { "setsystime",             DMPL_PRIV_CONFIGURE,                HrSetSystemTime         }, // Sets the system time
  3615.     { "shutdown",               DMPL_PRIV_CONTROL,                  HrShutdown              }, // Shuts down the console
  3616.     { "stop",                   DMPL_PRIV_CONTROL,                  HrStop                  }, // Stops all threads
  3617.     { "stopon",                 DMPL_PRIV_CONTROL,                  HrStopOn                }, // Changes what we stop on
  3618.     { "spew",                   DMPL_PRIV_CONTROL,                  HrSpew                  }, // Spews debug output
  3619.     { "suspend",                DMPL_PRIV_CONTROL,                  HrSuspendThread         }, // Suspends a thread
  3620.     { "systeminfo",             DMPL_PRIV_READ,                     HrGetSystemInfo         }, // Gets system info
  3621.     { "systime",                DMPL_PRIV_CONFIGURE,                HrGetSystemTime         }, // Sets the system time
  3622.     { "threadex",               DMPL_PRIV_CONTROL,                  HrListThreadsEx         }, // Lists threads in a different format
  3623.     { "threadinfo",             DMPL_PRIV_CONTROL,                  HrGetThreadInfo         }, // Returns info on a thread
  3624.     { "threads",                DMPL_PRIV_CONTROL,                  HrListThreads           }, // Gets a list of threads
  3625.     { "xbeinfo",                DMPL_PRIV_READ,                     HrGetXbeInfo            }, // Gets information on the running executable
  3626.     { "xexfield",               DMPL_PRIV_CONTROL,                  HrGetXexField           }, // Gets an xex field
  3627.     { "walkmem",                DMPL_PRIV_CONTROL,                  HrWalkMemory            }, // Lists memory and protection pages
  3628.     { "whomadethis",            DMPL_PRIV_CONTROL,                  HrWhoMadeThis           }, // Guess who
  3629. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement