Fixed "conditional expr is always true due to being unsigned < 0"
[wine/dcerpc.git] / dlls / winedos / dosaspi.c
blobaf17398750644c4ecb6a3b87c70f92f67f775115
1 /*
2 * Copyright 2000 David Elliott
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "config.h"
21 #include <string.h>
22 #include "winbase.h"
23 #include "wine/windef16.h"
24 #include "wine/winaspi.h"
25 #include "wine/debug.h"
26 #include "miscemu.h" /* DOSMEM_* */
27 #include "winerror.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(aspi);
31 static HINSTANCE hWNASPI32 = INVALID_HANDLE_VALUE;
32 static DWORD (__cdecl *pSendASPI32Command) (LPSRB) = NULL;
34 static void
35 DOSASPI_PostProc( SRB_ExecSCSICmd *lpPRB )
37 DWORD ptrSRB;
38 LPSRB16 lpSRB16;
41 memcpy(&ptrSRB,lpPRB->SenseArea + lpPRB->SRB_SenseLen,sizeof(DWORD));
42 TRACE("Copying data back to DOS client at 0x%8lx\n",ptrSRB);
43 lpSRB16 = PTR_REAL_TO_LIN(SELECTOROF(ptrSRB),OFFSETOF(ptrSRB));
44 lpSRB16->cmd.SRB_TargStat = lpPRB->SRB_TargStat;
45 lpSRB16->cmd.SRB_HaStat = lpPRB->SRB_HaStat;
46 memcpy(lpSRB16->cmd.CDBByte + lpSRB16->cmd.SRB_CDBLen,lpPRB->SenseArea,lpSRB16->cmd.SRB_SenseLen);
48 /* Now do posting */
49 if( lpPRB->SRB_Status == SS_SECURITY_VIOLATION )
51 /* SS_SECURITY_VIOLATION isn't defined in DOS ASPI */
52 TRACE("Returning SS_NO_DEVICE for SS_SECURITY_VIOLATION\n");
53 lpPRB->SRB_Status = SS_NO_DEVICE;
56 lpSRB16->cmd.SRB_Status = lpPRB->SRB_Status;
57 TRACE("SRB_Status = 0x%x\n", lpPRB->SRB_Status);
59 HeapFree(GetProcessHeap(),0,lpPRB);
61 if( (lpSRB16->cmd.SRB_Flags & SRB_POSTING) && lpSRB16->cmd.SRB_PostProc )
63 CONTEXT86 ctx;
64 /* The stack should look like this on entry to proc
65 * NOTE: the SDK draws the following diagram bass akwards, use this one
66 * to avoid being confused. Remember, the act of pushing something on
67 * an intel stack involves decreasing the stack pointer by the size of
68 * the data, and then copying the data at the new SP.
70 /***************************
71 * ... Other crap that is already on the stack ...
72 * Segment of SRB Pointer <- SP+6
73 * Offset of SRB Pointer <- SP+4
74 * Segment of return address <- SP+2
75 * Offset of return address <- SP+0
77 /* FIXME: I am about 99% sure what is here is correct,
78 * but this code has never been tested (and probably
79 * won't be either until someone finds a DOS program
80 * that actually uses a Post Routine) */
82 /* Zero everything */
83 memset(&ctx, 0, sizeof(ctx));
84 /* CS:IP is routine to call */
85 ctx.SegCs = SELECTOROF(lpSRB16->cmd.SRB_PostProc);
86 ctx.Eip = OFFSETOF(lpSRB16->cmd.SRB_PostProc);
87 /* DPMI_CallRMProc will push the pointer to the stack
88 * it is given (in this case &ptrSRB) with length
89 * 2*sizeof(WORD), that is, it copies the the contents
90 * of ptrSRB onto the stack, and decs sp by 2*sizeof(WORD).
91 * After doing that, it pushes the return address
92 * onto the stack (so we don't need to worry about that)
93 * So the stack should be okay for the PostProc
95 if(DPMI_CallRMProc(&ctx, (LPWORD)&ptrSRB, 2, FALSE))
97 TRACE("DPMI_CallRMProc returned nonzero (error) status\n");
99 } /* if ((SRB_Flags&SRB_POSTING) && SRB_PostProc) */
102 static
103 DWORD ASPI_SendASPIDOSCommand(DWORD ptrSRB)
105 PSRB_ExecSCSICmd lpPRB;
106 DWORD retval;
107 union tagSRB16 * lpSRB16;
109 lpSRB16 = PTR_REAL_TO_LIN(SELECTOROF(ptrSRB),OFFSETOF(ptrSRB));
111 retval = SS_ERR;
112 switch( lpSRB16->common.SRB_Cmd )
114 case SC_HA_INQUIRY:
115 TRACE("SC_HA_INQUIRY\n");
116 /* Format is identical in this case */
117 retval = (*pSendASPI32Command)((LPSRB)lpSRB16);
118 break;
119 case SC_GET_DEV_TYPE:
120 TRACE("SC_GET_DEV_TYPE\n");
121 /* Format is identical in this case */
122 retval = (*pSendASPI32Command)((LPSRB)lpSRB16);
123 break;
124 case SC_EXEC_SCSI_CMD:
125 TRACE("SC_EXEC_SCSI_CMD\n");
126 TRACE("Copying data from DOS client at 0x%8lx\n",ptrSRB);
127 lpPRB = HeapAlloc(GetProcessHeap(),0,sizeof(SRB)+lpSRB16->cmd.SRB_SenseLen+sizeof(DWORD));
128 #define srb_dos_to_w32(name) \
129 lpPRB->SRB_##name = lpSRB16->cmd.SRB_##name
131 srb_dos_to_w32(Cmd);
132 srb_dos_to_w32(Status);
133 srb_dos_to_w32(HaId);
134 srb_dos_to_w32(BufLen);
135 srb_dos_to_w32(SenseLen);
136 srb_dos_to_w32(CDBLen);
137 srb_dos_to_w32(Target);
138 srb_dos_to_w32(Lun);
139 #undef srb_dos_to_w32
141 /* Allow certain flags to go on to WNASPI32, we also need
142 * to make sure SRB_POSTING is enabled */
143 lpPRB->SRB_Flags = SRB_POSTING | (lpSRB16->cmd.SRB_Flags&(SRB_DIR_IN|SRB_DIR_OUT|SRB_ENABLE_RESIDUAL_COUNT));
145 /* Pointer to data buffer */
146 lpPRB->SRB_BufPointer = PTR_REAL_TO_LIN(SELECTOROF(lpSRB16->cmd.SRB_BufPointer),
147 OFFSETOF(lpSRB16->cmd.SRB_BufPointer));
148 /* Copy CDB in */
149 memcpy(&lpPRB->CDBByte[0],&lpSRB16->cmd.CDBByte[0],lpSRB16->cmd.SRB_CDBLen);
151 /* Set post proc to our post proc */
152 lpPRB->SRB_PostProc = &DOSASPI_PostProc;
154 /* Stick the DWORD after all the sense info */
155 memcpy(lpPRB->SenseArea + lpPRB->SRB_SenseLen,&ptrSRB,sizeof(DWORD));
156 retval = (*pSendASPI32Command)((LPSRB)lpPRB);
157 break;
158 case SC_ABORT_SRB:
159 TRACE("SC_ABORT_SRB\n");
160 /* Would need some sort of table of active shit */
161 break;
162 case SC_RESET_DEV:
163 TRACE("SC_RESET_DEV\n");
164 break;
165 default:
166 TRACE("Unkown command code\n");
167 break;
170 TRACE("Returning %lx\n", retval );
171 return retval;
174 void WINAPI ASPI_DOS_func(CONTEXT86 *context)
176 WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
177 DWORD ptrSRB = *(DWORD *)&stack[2];
179 ASPI_SendASPIDOSCommand(ptrSRB);
181 /* simulate a normal RETF sequence as required by DPMI CallRMProcFar */
182 context->Eip = *(stack++);
183 context->SegCs = *(stack++);
184 context->Esp += 2*sizeof(WORD);
188 /**********************************************************************
189 * ASPIHandler (WINEDOS.@)
191 * returns the address of a real mode callback to ASPI_DOS_func()
193 void WINAPI DOSVM_ASPIHandler( CONTEXT86 *context )
195 FARPROC16 *p = (FARPROC16 *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
196 TRACE("DOS ASPI opening\n");
197 if ((CX_reg(context) == 4) || (CX_reg(context) == 5))
199 if( hWNASPI32 == INVALID_HANDLE_VALUE )
201 TRACE("Loading WNASPI32\n");
202 hWNASPI32 = LoadLibraryExA("WNASPI32", 0, 0);
205 if( hWNASPI32 == INVALID_HANDLE_VALUE )
207 ERR("Error loading WNASPI32\n");
208 goto error_exit;
211 /* Get SendASPI32Command by Ordinal 2 */
212 /* Cast to correct argument/return types */
213 pSendASPI32Command = (DWORD (*)(LPSRB))GetProcAddress(hWNASPI32, (LPBYTE)2);
214 if( !pSendASPI32Command )
216 ERR("Error getting ordinal 2 from WNASPI32\n");
217 goto error_exit;
220 *p = DPMI_AllocInternalRMCB(ASPI_DOS_func);
221 TRACE("allocated real mode proc %p\n", *p);
222 SET_AX( context, CX_reg(context) );
224 return;
226 error_exit:
227 /* Return some error... General Failure sounds okay */
228 SET_AX( context, ERROR_GEN_FAILURE );
229 SET_CFLAG(context);