//+---------------------------------------------------------------------------- // // Copyright (C) 1992, Microsoft Corporation // // File: dfsmrshl.c // // Contents: Routines to handle marshalling of data structures. This file // has been specifically created so that user level code can // avail of the marshalling code simply by including this file. // // Classes: // // Functions: // // History: March 29, 1994 Milans created from PeterCo's routines // //----------------------------------------------------------------------------- #ifdef KERNEL_MODE #include "dfsprocs.h" #include "dfsmrshl.h" #include "dfsrtl.h" #define Dbg (DEBUG_TRACE_RTL) #else // !KERNEL_MODE #include "dfsmrshl.h" #ifndef ExRaiseStatus #define ExRaiseStatus(x) RtlRaiseStatus(x) #endif // ExRaiseStatus #ifndef try_return #define try_return(s) {s; goto try_exit;} #endif // try_return #ifndef DfsDbgTrace #define DfsDbgTrace(i,l,f,s) #endif // DfsDbgTrace #endif // KERNEL_MODE NTSTATUS DfsRtlGetpwString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PWSTR *ppwszString ); NTSTATUS DfsRtlPutpwString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PWSTR *ppwszString ); NTSTATUS DfsRtlGetString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PSTRING String ); NTSTATUS DfsRtlPutString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PSTRING String ); NTSTATUS DfsRtlGetArrayUchar( IN OUT PMARSHAL_BUFFER MarshalBuffer, IN ULONG cbArray, OUT PUCHAR pArray); NTSTATUS DfsRtlPutArrayUchar( IN OUT PMARSHAL_BUFFER MarshalBuffer, IN ULONG cbArray, OUT PUCHAR pArray); #ifdef ALLOC_PRAGMA #pragma alloc_text( PAGE, DfsRtlGetpwString ) #pragma alloc_text( PAGE, DfsRtlPutpwString ) #pragma alloc_text( PAGE, DfsRtlGetString ) #pragma alloc_text( PAGE, DfsRtlPutString ) #pragma alloc_text( PAGE, DfsRtlGetArrayUchar ) #pragma alloc_text( PAGE, DfsRtlPutArrayUchar ) #pragma alloc_text( PAGE, DfsRtlGet ) #pragma alloc_text( PAGE, DfsRtlPut ) #pragma alloc_text( PAGE, DfsRtlSize ) #pragma alloc_text( PAGE, DfsRtlUnwindGet ) #endif //ALLOC_PRAGMA #define UNREFERENCED_LABEL(label)\ if(0) goto label; // // Defines and functions for unmarshalling base types. // Regarding the BYTE macros below we dont care whether we are on // LITTLE ENDIAN or BIG ENDIAN. It just does not matter. // #define BYTE_0_MASK 0xFF #define BYTE_0(Value) (UCHAR)( (Value) & BYTE_0_MASK) #define BYTE_1(Value) (UCHAR)( ((Value) >> 8) & BYTE_0_MASK) #define BYTE_2(Value) (UCHAR)( ((Value) >> 16) & BYTE_0_MASK) #define BYTE_3(Value) (UCHAR)( ((Value) >> 24) & BYTE_0_MASK) #define DfsRtlGetUchar(MarshalBuffer, pValue) ( \ ((MarshalBuffer)->Current + 1 <= (MarshalBuffer)->Last) ? \ *(pValue) = (UCHAR)((MarshalBuffer)->Current[0] ), \ (MarshalBuffer)->Current += 1, \ STATUS_SUCCESS \ : STATUS_DATA_ERROR \ ) #define DfsRtlPutUchar(MarshalBuffer, pValue) ( \ ((MarshalBuffer)->Current + 1 <= (MarshalBuffer)->Last) ? \ (MarshalBuffer)->Current[0] = BYTE_0(*pValue), \ (MarshalBuffer)->Current += 1, \ STATUS_SUCCESS \ : STATUS_BUFFER_TOO_SMALL \ ) #define DfsRtlGetUshort(MarshalBuffer, pValue) ( \ ((MarshalBuffer)->Current + 2 <= (MarshalBuffer)->Last) ? \ *(pValue) = (USHORT)((MarshalBuffer)->Current[0] ) | \ ((MarshalBuffer)->Current[1] << 8), \ (MarshalBuffer)->Current += 2, \ STATUS_SUCCESS \ : STATUS_DATA_ERROR \ ) #define DfsRtlPutUshort(MarshalBuffer, pValue) ( \ ((MarshalBuffer)->Current + 2 <= (MarshalBuffer)->Last) ? \ (MarshalBuffer)->Current[0] = BYTE_0(*pValue), \ (MarshalBuffer)->Current[1] = BYTE_1(*pValue), \ (MarshalBuffer)->Current += 2, \ STATUS_SUCCESS \ : STATUS_BUFFER_TOO_SMALL \ ) #define DfsRtlGetUlong(MarshalBuffer, pValue) ( \ ((MarshalBuffer)->Current + 4 <= (MarshalBuffer)->Last) ? \ *(pValue) = (ULONG) ((MarshalBuffer)->Current[0] ) | \ ((MarshalBuffer)->Current[1] << 8) | \ ((MarshalBuffer)->Current[2] << 16) | \ ((MarshalBuffer)->Current[3] << 24), \ (MarshalBuffer)->Current += 4, \ STATUS_SUCCESS \ : STATUS_DATA_ERROR \ ) #define DfsRtlPutUlong(MarshalBuffer, pValue) ( \ ((MarshalBuffer)->Current + 4 <= (MarshalBuffer)->Last) ? \ (MarshalBuffer)->Current[0] = BYTE_0(*pValue), \ (MarshalBuffer)->Current[1] = BYTE_1(*pValue), \ (MarshalBuffer)->Current[2] = BYTE_2(*pValue), \ (MarshalBuffer)->Current[3] = BYTE_3(*pValue), \ (MarshalBuffer)->Current += 4, \ STATUS_SUCCESS \ : STATUS_BUFFER_TOO_SMALL \ ) #define DfsRtlGetGuid(MarshalBuffer, pValue) ( \ ((MarshalBuffer)->Current + 16 <= (MarshalBuffer)->Last) ? \ (pValue)->Data1 = (ULONG) ((MarshalBuffer)->Current[0] ) | \ ((MarshalBuffer)->Current[1] << 8) | \ ((MarshalBuffer)->Current[2] << 16) | \ ((MarshalBuffer)->Current[3] << 24) , \ (pValue)->Data2 = (USHORT)((MarshalBuffer)->Current[4] ) | \ ((MarshalBuffer)->Current[5] << 8) , \ (pValue)->Data3 = (USHORT)((MarshalBuffer)->Current[6] ) | \ ((MarshalBuffer)->Current[7] << 8) , \ memcpy((pValue)->Data4, &(MarshalBuffer)->Current[8], 8), \ (MarshalBuffer)->Current += 16, \ STATUS_SUCCESS \ : STATUS_DATA_ERROR \ ) #define DfsRtlPutGuid(MarshalBuffer, pValue) ( \ ((MarshalBuffer)->Current + 16 <= (MarshalBuffer)->Last) ? \ (MarshalBuffer)->Current[0] = BYTE_0((pValue)->Data1), \ (MarshalBuffer)->Current[1] = BYTE_1((pValue)->Data1), \ (MarshalBuffer)->Current[2] = BYTE_2((pValue)->Data1), \ (MarshalBuffer)->Current[3] = BYTE_3((pValue)->Data1), \ (MarshalBuffer)->Current[4] = BYTE_0((pValue)->Data2), \ (MarshalBuffer)->Current[5] = BYTE_1((pValue)->Data2), \ (MarshalBuffer)->Current[6] = BYTE_0((pValue)->Data3), \ (MarshalBuffer)->Current[7] = BYTE_1((pValue)->Data3), \ memcpy(&(MarshalBuffer)->Current[8], (pValue)->Data4, 8), \ (MarshalBuffer)->Current += 16, \ STATUS_SUCCESS \ : STATUS_BUFFER_TOO_SMALL \ ) #define DfsRtlSizeString(pString, pSize) ( \ ((pString)->Length > 0) ? ( \ ((pString)->Buffer != NULL) ? \ (*(pSize)) += (2 + (pString)->Length), \ STATUS_SUCCESS \ : STATUS_DATA_ERROR \ ) \ : ((*(pSize)) += 2, \ STATUS_SUCCESS) \ ) #define DfsRtlSizepwString(pString, pSize) ( \ (*pString != NULL) ? \ (*(pSize)) += ((1 + wcslen(*pString))*sizeof(WCHAR)), \ STATUS_SUCCESS \ : ((*(pSize)) += 2, \ STATUS_SUCCESS) \ ) #define DfsRtlSizeUnicodeString(pUnicodeString, pSize) \ DfsRtlSizeString(pUnicodeString, pSize) #define DfsRtlUnwindStringGet(s) { \ if((s)->Length != 0) \ MarshalBufferFree(s); \ } #define DfsRtlUnwindpwStringGet(s) { \ if(s != NULL) \ MarshalBufferFree(s); \ } #define DfsRtlUnwindUnicodeStringGet(s) \ DfsRtlUnwindStringGet(s) NTSTATUS DfsRtlGetArrayUchar( IN OUT PMARSHAL_BUFFER MarshalBuffer, IN ULONG cbArray, OUT PUCHAR pArray) { NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlGetArrayUchar: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(pArray)); try { UNREFERENCED_LABEL(try_exit); if (MarshalBuffer->Current + cbArray <= MarshalBuffer->Last) { memcpy(pArray, MarshalBuffer->Current, cbArray); MarshalBuffer->Current += cbArray; } else { status = STATUS_DATA_ERROR; } try_exit: NOTHING; } finally { if (AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlGetArrayUchar - Abnormal termination!\n", 0); status = STATUS_DATA_ERROR; } } DfsDbgTrace(-1, Dbg, "DfsRtlGetArrayUchar: Exited %08lx\n", status); return(status); } NTSTATUS DfsRtlPutArrayUchar( IN OUT PMARSHAL_BUFFER MarshalBuffer, IN ULONG cbArray, OUT PUCHAR pArray) { NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlGetArrayUchar: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(pArray)); try { UNREFERENCED_LABEL(try_exit); if (MarshalBuffer->Current + cbArray <= MarshalBuffer->Last) { if (cbArray) { memcpy(MarshalBuffer->Current, pArray, cbArray); MarshalBuffer->Current += cbArray; } } else { status = STATUS_BUFFER_TOO_SMALL; } try_exit: NOTHING; } finally { if (AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlPutArrayUchar - Abnormal termination!\n", 0); status = STATUS_DATA_ERROR; } } DfsDbgTrace(-1, Dbg, "DfsRtlPutArrayUchar: Exited %08lx\n", status); return(status); } NTSTATUS DfsRtlGetpwString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PWSTR *ppwszString ) { USHORT size; PCHAR cp = NULL; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlGetpwString: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(ppwszString)); try { UNREFERENCED_LABEL(try_exit); *ppwszString = NULL; if(NT_SUCCESS(status = DfsRtlGetUshort(MarshalBuffer, &size))) { if(size > 0) { if(MarshalBuffer->Current + size <= MarshalBuffer->Last) { if((cp = MarshalBufferAllocate(size+sizeof(WCHAR))) != NULL) { memcpy(cp, MarshalBuffer->Current, size); *((WCHAR *) (cp + size)) = UNICODE_NULL; *ppwszString = (PWCHAR) cp; MarshalBuffer->Current += size; } else status = STATUS_INSUFFICIENT_RESOURCES; } else status = STATUS_DATA_ERROR; } } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlGetpwString: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } if(!NT_SUCCESS(status) && cp) MarshalBufferFree(cp); } DfsDbgTrace(-1, Dbg, "DfsRtlGetpwString: Exit -> %08lx\n",status); return status; } NTSTATUS DfsRtlPutpwString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PWSTR *ppwszString ) { USHORT size; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlPutpwString: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(ppwszString)); try { UNREFERENCED_LABEL(try_exit); if (*ppwszString != NULL) size = wcslen(*ppwszString)*sizeof(WCHAR); else size = 0; if(NT_SUCCESS(status = DfsRtlPutUshort(MarshalBuffer, &size))) { if(size > 0) { if(MarshalBuffer->Current + size <= MarshalBuffer->Last) { memcpy(MarshalBuffer->Current, *ppwszString, size); MarshalBuffer->Current += size; } else status = STATUS_BUFFER_TOO_SMALL; } } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlPutString: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } } DfsDbgTrace(-1, Dbg, "DfsRtlPutString: Exit -> %08lx\n",status); return status; } NTSTATUS DfsRtlGetString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PSTRING String ) { USHORT size; PCHAR cp = NULL; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlGetString: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(String)); try { UNREFERENCED_LABEL(try_exit); String->Length = String->MaximumLength = 0; String->Buffer = NULL; if(NT_SUCCESS(status = DfsRtlGetUshort(MarshalBuffer, &size))) { if(size > 0) { if(MarshalBuffer->Current + size <= MarshalBuffer->Last) { if((cp = MarshalBufferAllocate(size+sizeof(WCHAR))) != NULL) { memcpy(cp, MarshalBuffer->Current, size); *((WCHAR *) (cp + size)) = UNICODE_NULL; String->Length = size; String->MaximumLength = size + sizeof(WCHAR); String->Buffer = cp; MarshalBuffer->Current += size; } else status = STATUS_INSUFFICIENT_RESOURCES; } else status = STATUS_DATA_ERROR; } } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlGetString: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } if(!NT_SUCCESS(status) && cp) MarshalBufferFree(cp); } DfsDbgTrace(-1, Dbg, "DfsRtlGetString: Exit -> %08lx\n",status); return status; } NTSTATUS DfsRtlPutString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PSTRING String ) { USHORT size; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlPutString: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(String)); try { UNREFERENCED_LABEL(try_exit); size = String->Length; if(NT_SUCCESS(status = DfsRtlPutUshort(MarshalBuffer, &size))) { if(size > 0) { if(MarshalBuffer->Current + size <= MarshalBuffer->Last) { if(String->Buffer != NULL) { memcpy(MarshalBuffer->Current, String->Buffer, size); MarshalBuffer->Current += size; } else status = STATUS_DATA_ERROR; } else status = STATUS_BUFFER_TOO_SMALL; } } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlPutString: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } } DfsDbgTrace(-1, Dbg, "DfsRtlPutString: Exit -> %08lx\n",status); return status; } #ifdef NOT_NEEDED NTSTATUS DfsRtlGetUnicodeString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PUNICODE_STRING UnicodeString ) { USHORT size; PWCHAR wcp = NULL; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlGetUnicodeString: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(UnicodeString)); try { UnicodeString->Length = UnicodeString->MaximumLength = 0; UnicodeString->Buffer = NULL; if(NT_SUCCESS(status = DfsRtlGetUshort(MarshalBuffer, &size))) { if(size > 0) { if(MarshalBuffer->Current + size <= MarshalBuffer->Last) { if((wcp = (MarshalBufferAllocate)(size+sizeof(WCHAR))) != NULL) { memcpy(wcp, MarshalBuffer->Current, size); wcp[size/sizeof(WCHAR)] = UNICODE_NULL; UnicodeString->Length = size; UnicodeString->MaximumLength = size + sizeof(WCHAR); UnicodeString->Buffer = wcp; MarshalBuffer->Current += size; } else status = STATUS_INSUFFICIENT_RESOURCES; } else status = STATUS_DATA_ERROR; } } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlGetUnicodeString: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } if(!NT_SUCCESS(status) && wcp) MarshalBufferFree(wcp); } DfsDbgTrace(-1, Dbg, "DfsRtlGetUnicodeString: Exit -> %08lx\n", status); return status; } NTSTATUS DfsRtlPutUnicodeString( IN OUT PMARSHAL_BUFFER MarshalBuffer, OUT PUNICODE_STRING UnicodeString ) { USHORT size; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlPutUnicodeString: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(UnicodeString)); try { size = UnicodeString->Length; if(NT_SUCCESS(status = DfsRtlPutUshort(MarshalBuffer, &size))) { if(size > 0) { if(MarshalBuffer->Current + size <= MarshalBuffer->Last) { if(UnicodeString->Buffer != NULL) { memcpy( MarshalBuffer->Current, UnicodeString->Buffer, size ); MarshalBuffer->Current += size; } else status = STATUS_DATA_ERROR; } else status = STATUS_BUFFER_TOO_SMALL; } } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlPutUnicodeString: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } } DfsDbgTrace(-1, Dbg, "DfsRtlPutUnicodeString: Exit -> %08lx\n", status); return status; } #else // NOT_NEEDED #define DfsRtlGetUnicodeString(b, s)\ DfsRtlGetString(b, (PSTRING)(s)) #define DfsRtlPutUnicodeString(b, s)\ DfsRtlPutString(b, (PSTRING)(s)) #endif // NOT_NEEDED NTSTATUS DfsRtlGet( IN OUT PMARSHAL_BUFFER MarshalBuffer, IN PMARSHAL_INFO MarshalInfo, OUT PVOID Item ) { PMARSHAL_TYPE_INFO typeInfo; PVOID subItem; PVOID subItemElem; ULONG cnt; ULONG unwindcnt; PUCHAR cntptr; ULONG itemSize; PMARSHAL_INFO subInfo; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlGet: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(MarshalInfo)); ASSERT(ARGUMENT_PRESENT(Item)); try { RtlZeroMemory(Item, MarshalInfo->_size); for(typeInfo = &MarshalInfo->_typeInfo[0]; typeInfo < &MarshalInfo->_typeInfo[MarshalInfo->_typecnt]; typeInfo++) { switch(typeInfo->_type & MTYPE_BASE_TYPE) { case MTYPE_COMPOUND: subInfo = typeInfo->_subinfo; itemSize = subInfo->_size; // // If this compound type is a conformant structure, then // we need to adjust the size field here. // if (subInfo->_typecnt > 0 && subInfo->_typeInfo[0]._type == MTYPE_CONFORMANT_CNT) { MARSHAL_BUFFER tempMarshalBuffer = *MarshalBuffer; ULONG extraSize = 0; DfsRtlGetUlong(&tempMarshalBuffer, &extraSize); itemSize += extraSize; } break; case MTYPE_CONFORMANT_CNT: itemSize = 0; break; case MTYPE_GUID: itemSize = sizeof(GUID); break; case MTYPE_STRING: itemSize = sizeof(STRING); break; case MTYPE_UNICODE_STRING: itemSize = sizeof(UNICODE_STRING); break; case MTYPE_PWSTR: itemSize = sizeof(PWSTR); break; case MTYPE_ULONG: itemSize = sizeof(ULONG); break; case MTYPE_USHORT: itemSize = sizeof(USHORT); break; case MTYPE_UCHAR: itemSize = sizeof(UCHAR); break; default: try_return(status = STATUS_DATA_ERROR); } if(typeInfo->_type & MTYPE_COUNTED_ARRAY) { cntptr = ((PUCHAR)Item + typeInfo->_cntoff); switch(typeInfo->_cntsize) { case sizeof(UCHAR): cnt = *(PUCHAR)cntptr; break; case sizeof(USHORT): cnt = *(PUSHORT)cntptr; break; case sizeof(ULONG): cnt = *(PULONG)cntptr; break; default: try_return(status = STATUS_DATA_ERROR); } } else if (typeInfo->_type & MTYPE_STATIC_ARRAY) { cnt = typeInfo->_cntoff; } else { cnt = 1; } if(typeInfo->_type & MTYPE_INDIRECT) { if((typeInfo->_type & MTYPE_COUNTED_ARRAY) && cnt == 0) subItem = NULL; else { subItem = MarshalBufferAllocate(itemSize * cnt); if(subItem == NULL) try_return(status = STATUS_INSUFFICIENT_RESOURCES); } *(PVOID *)((PUCHAR)Item + typeInfo->_off) = subItem; } else subItem = ((PUCHAR)Item + typeInfo->_off); switch(typeInfo->_type & ~MTYPE_INDIRECT) { case MTYPE_COMPOUND: status = DfsRtlGet( MarshalBuffer, subInfo, subItem ); break; case MTYPE_CONFORMANT_CNT: // // this field is used only when sizing a conformant // structure. As such, there is no place to unmarshal // it into. So, simply eat the ulong. // status = DfsRtlGetUlong(MarshalBuffer, &itemSize); break; case (MTYPE_COMPOUND|MTYPE_COUNTED_ARRAY): case (MTYPE_COMPOUND|MTYPE_STATIC_ARRAY): subItemElem = (PUCHAR)subItem; unwindcnt = cnt; while(cnt--) { status = DfsRtlGet( MarshalBuffer, subInfo, subItemElem ); if(!NT_SUCCESS(status)) { while((++cnt) < unwindcnt) { ((PUCHAR)subItemElem) -= itemSize; DfsRtlUnwindGet( subInfo, &subInfo->_typeInfo[subInfo->_typecnt], subItemElem ); } if(typeInfo->_type & MTYPE_INDIRECT) MarshalBufferFree(subItem); break; } ((PUCHAR)subItemElem) += itemSize; } break; case MTYPE_GUID: status = DfsRtlGetGuid( MarshalBuffer, (GUID *)subItem ); break; case MTYPE_STRING: status = DfsRtlGetString( MarshalBuffer, (PSTRING)subItem ); break; case MTYPE_UNICODE_STRING: status = DfsRtlGetUnicodeString( MarshalBuffer, (PUNICODE_STRING)subItem ); break; case MTYPE_PWSTR: status = DfsRtlGetpwString( MarshalBuffer, (PWSTR *)subItem ); break; case (MTYPE_PWSTR|MTYPE_COUNTED_ARRAY): case (MTYPE_PWSTR|MTYPE_STATIC_ARRAY): subItemElem = (PUCHAR)subItem; unwindcnt = cnt; while (cnt--) { status = DfsRtlGetpwString( MarshalBuffer, (PWSTR *)subItemElem); if (!NT_SUCCESS(status)) { while ((+cnt) < unwindcnt) { ((PUCHAR)subItemElem) -= itemSize; MarshalBufferFree((PVOID)*(PWSTR *)subItemElem); } if (typeInfo->_type & MTYPE_INDIRECT) { MarshalBufferFree(subItem); } break; } ((PUCHAR)subItemElem) += itemSize; } break; case (MTYPE_UNICODE_STRING|MTYPE_COUNTED_ARRAY): case (MTYPE_UNICODE_STRING|MTYPE_STATIC_ARRAY): subItemElem = (PUCHAR)subItem; unwindcnt = cnt; while(cnt--) { status = DfsRtlGetUnicodeString( MarshalBuffer, (PUNICODE_STRING)subItemElem ); if(!NT_SUCCESS(status)) { while((++cnt) < unwindcnt) { ((PUCHAR)subItemElem) -= itemSize; DfsRtlUnwindUnicodeStringGet( (PUNICODE_STRING)subItemElem ); } if(typeInfo->_type & MTYPE_INDIRECT) MarshalBufferFree(subItem); break; } ((PUCHAR)subItemElem) += itemSize; } break; case MTYPE_ULONG: status = DfsRtlGetUlong( MarshalBuffer, (PULONG)subItem ); break; case MTYPE_USHORT: status = DfsRtlGetUshort( MarshalBuffer, (PUSHORT)subItem); break; case MTYPE_UCHAR: status = DfsRtlGetUchar( MarshalBuffer, (PUCHAR)subItem); break; case MTYPE_UCHAR|MTYPE_COUNTED_ARRAY: case MTYPE_UCHAR|MTYPE_STATIC_ARRAY: status = DfsRtlGetArrayUchar( MarshalBuffer, cnt, (PUCHAR)subItem); break; default: status = STATUS_DATA_ERROR; break; }; if(!NT_SUCCESS(status)) break; } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlGet: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } if(!NT_SUCCESS(status)) DfsRtlUnwindGet(MarshalInfo, typeInfo, Item); } DfsDbgTrace(-1, Dbg, "DfsRtlGet: Exit -> %08lx\n", status); return status; } NTSTATUS DfsRtlPut( IN OUT PMARSHAL_BUFFER MarshalBuffer, IN PMARSHAL_INFO MarshalInfo, OUT PVOID Item ) { PMARSHAL_TYPE_INFO typeInfo; PVOID subItem; PVOID subItemElem; ULONG cnt; PUCHAR cntptr; ULONG itemSize; PMARSHAL_INFO subInfo; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlPut: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalBuffer)); ASSERT(ARGUMENT_PRESENT(MarshalInfo)); ASSERT(ARGUMENT_PRESENT(Item)); try { for(typeInfo = &MarshalInfo->_typeInfo[0]; typeInfo < &MarshalInfo->_typeInfo[MarshalInfo->_typecnt]; typeInfo++) { switch(typeInfo->_type & MTYPE_BASE_TYPE) { case MTYPE_COMPOUND: subInfo = typeInfo->_subinfo; itemSize = subInfo->_size; break; case MTYPE_CONFORMANT_CNT: itemSize = typeInfo->_off; break; case MTYPE_GUID: itemSize = sizeof(GUID); break; case MTYPE_STRING: itemSize = sizeof(STRING); break; case MTYPE_UNICODE_STRING: itemSize = sizeof(UNICODE_STRING); break; case MTYPE_PWSTR: itemSize = sizeof(PWSTR); break; case MTYPE_ULONG: itemSize = sizeof(ULONG); break; case MTYPE_USHORT: itemSize = sizeof(USHORT); break; case MTYPE_UCHAR: itemSize = sizeof(UCHAR); break; default: try_return(status = STATUS_DATA_ERROR); } if(typeInfo->_type & MTYPE_COUNTED_ARRAY || typeInfo->_type == MTYPE_CONFORMANT_CNT) { cntptr = ((PUCHAR)Item + typeInfo->_cntoff); switch(typeInfo->_cntsize) { case sizeof(UCHAR): cnt = *(PUCHAR)cntptr; break; case sizeof(USHORT): cnt = *(PUSHORT)cntptr; break; case sizeof(ULONG): cnt = *(PULONG)cntptr; break; default: try_return(status = STATUS_DATA_ERROR); } } else cnt = typeInfo->_cntoff; if(typeInfo->_type & MTYPE_INDIRECT) { subItem = *(PUCHAR *)((PUCHAR)Item + typeInfo->_off); if(subItem == NULL && !((typeInfo->_type & MTYPE_COUNTED_ARRAY) && cnt == 0)) try_return(status = STATUS_DATA_ERROR); } else subItem = ((PUCHAR)Item + typeInfo->_off); switch(typeInfo->_type & ~MTYPE_INDIRECT) { case MTYPE_COMPOUND: status = DfsRtlPut( MarshalBuffer, subInfo, subItem ); break; case MTYPE_CONFORMANT_CNT: cnt *= itemSize; status = DfsRtlPutUlong( MarshalBuffer, &cnt); break; case (MTYPE_COMPOUND|MTYPE_COUNTED_ARRAY): case (MTYPE_COMPOUND|MTYPE_STATIC_ARRAY): // // No sense in having an array of conformant structures // ASSERT this fact // ASSERT(subInfo->_typecnt == 0 || subInfo->_typeInfo[0]._type != MTYPE_CONFORMANT_CNT ); subItemElem = (PUCHAR)subItem; while(cnt--) { status = DfsRtlPut( MarshalBuffer, subInfo, subItemElem ); if(!NT_SUCCESS(status)) break; ((PUCHAR)subItemElem) += itemSize; } break; case MTYPE_GUID: status = DfsRtlPutGuid( MarshalBuffer, (GUID *)subItem ); break; case MTYPE_STRING: status = DfsRtlPutString( MarshalBuffer, (PSTRING)subItem ); break; case MTYPE_UNICODE_STRING: status = DfsRtlPutUnicodeString( MarshalBuffer, (PUNICODE_STRING)subItem ); break; case MTYPE_PWSTR: status = DfsRtlPutpwString( MarshalBuffer, (PWSTR *)subItem ); break; case (MTYPE_PWSTR|MTYPE_COUNTED_ARRAY): case (MTYPE_PWSTR|MTYPE_STATIC_ARRAY): subItemElem = (PWSTR *)subItem; while(cnt--) { status = DfsRtlPutpwString( MarshalBuffer, (PWSTR *)subItemElem); if (!NT_SUCCESS(status)) break; ((PUCHAR)subItemElem) += itemSize; } break; case (MTYPE_UNICODE_STRING|MTYPE_COUNTED_ARRAY): case (MTYPE_UNICODE_STRING|MTYPE_STATIC_ARRAY): subItemElem = (PUCHAR)subItem; while(cnt--) { status = DfsRtlPutUnicodeString( MarshalBuffer, (PUNICODE_STRING)subItemElem ); if(!NT_SUCCESS(status)) break; ((PUCHAR)subItemElem) += itemSize; } break; case MTYPE_ULONG: status = DfsRtlPutUlong( MarshalBuffer, (PULONG)subItem ); break; case MTYPE_USHORT: status = DfsRtlPutUshort( MarshalBuffer, (PUSHORT)subItem); break; case MTYPE_UCHAR: status = DfsRtlPutUchar( MarshalBuffer, (PUCHAR)subItem); break; case (MTYPE_UCHAR|MTYPE_COUNTED_ARRAY): case (MTYPE_UCHAR|MTYPE_STATIC_ARRAY): status = DfsRtlPutArrayUchar( MarshalBuffer, cnt, (PUCHAR)subItem); break; default: status = STATUS_DATA_ERROR; break; } if(!NT_SUCCESS(status)) break; } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlPut: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } } DfsDbgTrace(-1, Dbg, "DfsRtlPut: Exit -> %08lx\n", status); return status; } NTSTATUS DfsRtlSize( IN PMARSHAL_INFO MarshalInfo, IN PVOID Item, OUT PULONG Size ) { PMARSHAL_TYPE_INFO typeInfo; PVOID subItem; PVOID subItemElem; ULONG cnt; PUCHAR cntptr; ULONG itemSize; PMARSHAL_INFO subInfo; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlSize: Entered\n", 0); ASSERT(ARGUMENT_PRESENT(MarshalInfo)); ASSERT(ARGUMENT_PRESENT(Item)); ASSERT(ARGUMENT_PRESENT(Size)); try { for(typeInfo = &MarshalInfo->_typeInfo[0]; typeInfo < &MarshalInfo->_typeInfo[MarshalInfo->_typecnt]; typeInfo++) { switch(typeInfo->_type & MTYPE_BASE_TYPE) { case MTYPE_COMPOUND: subInfo = typeInfo->_subinfo; itemSize = subInfo->_size; break; case MTYPE_CONFORMANT_CNT: // // For conformant structures, _offset is sizeof each // element, _cntsize is sizeof cnt field, and _cntoff is // offset of cnt field. // itemSize = typeInfo->_off; break; case MTYPE_GUID: itemSize = sizeof(GUID); break; case MTYPE_STRING: itemSize = sizeof(STRING); break; case MTYPE_UNICODE_STRING: itemSize = sizeof(UNICODE_STRING); break; case MTYPE_PWSTR: itemSize = sizeof(PWCHAR); break; case MTYPE_ULONG: itemSize = sizeof(ULONG); break; case MTYPE_USHORT: itemSize = sizeof(USHORT); break; case MTYPE_UCHAR: itemSize = sizeof(UCHAR); break; default: try_return(status = STATUS_DATA_ERROR); } if(typeInfo->_type & MTYPE_COUNTED_ARRAY || typeInfo->_type == MTYPE_CONFORMANT_CNT) { cntptr = ((PUCHAR)Item + typeInfo->_cntoff); switch(typeInfo->_cntsize) { case sizeof(UCHAR): cnt = *(PUCHAR)cntptr; break; case sizeof(USHORT): cnt = *(PUSHORT)cntptr; break; case sizeof(ULONG): cnt = *(PULONG)cntptr; break; default: try_return(status = STATUS_DATA_ERROR); } } else cnt = typeInfo->_cntoff; if(typeInfo->_type & MTYPE_INDIRECT) { subItem = *(PUCHAR *)((PUCHAR)Item + typeInfo->_off); if(subItem == NULL && !((typeInfo->_type & MTYPE_COUNTED_ARRAY) && cnt == 0)) try_return(status = STATUS_DATA_ERROR); } else subItem = ((PUCHAR)Item + typeInfo->_off); switch(typeInfo->_type & ~MTYPE_INDIRECT) { case MTYPE_COMPOUND: status = DfsRtlSize( subInfo, subItem, Size ); break; case MTYPE_CONFORMANT_CNT: (*Size) += sizeof(ULONG); break; case (MTYPE_COMPOUND|MTYPE_COUNTED_ARRAY): case (MTYPE_COMPOUND|MTYPE_STATIC_ARRAY): // // No sense in having an array of conformant structures // ASSERT this fact // ASSERT(subInfo->_typecnt == 0 || subInfo->_typeInfo[0]._type != MTYPE_CONFORMANT_CNT ); subItemElem = (PUCHAR)subItem; while(cnt--) { status = DfsRtlSize( subInfo, subItemElem, Size ); if(!NT_SUCCESS(status)) break; ((PUCHAR)subItemElem) += itemSize; } break; case MTYPE_GUID: (*Size) += 16; break; case MTYPE_STRING: status = DfsRtlSizeString( (PSTRING)subItem, Size ); break; case MTYPE_UNICODE_STRING: status = DfsRtlSizeUnicodeString( (PUNICODE_STRING)subItem, Size ); break; case MTYPE_PWSTR: status = DfsRtlSizepwString( (PWSTR *)subItem, Size ); break; case (MTYPE_PWSTR|MTYPE_COUNTED_ARRAY): case (MTYPE_PWSTR|MTYPE_STATIC_ARRAY): subItemElem = (PUCHAR)subItem; while (cnt--) { status = DfsRtlSizepwString( (PWSTR *)subItemElem, Size); if (!NT_SUCCESS(status)) { break; } ((PUCHAR)subItemElem) += itemSize; } break; case (MTYPE_UNICODE_STRING|MTYPE_COUNTED_ARRAY): case (MTYPE_UNICODE_STRING|MTYPE_STATIC_ARRAY): subItemElem = (PUCHAR)subItem; while(cnt--) { status = DfsRtlSizeUnicodeString( (PUNICODE_STRING)subItemElem, Size ); if(!NT_SUCCESS(status)) break; ((PUCHAR)subItemElem) += itemSize; } break; case MTYPE_ULONG: (*Size) += 4; break; case MTYPE_USHORT: (*Size) += 2; break; case MTYPE_UCHAR: (*Size) += 1; break; case MTYPE_UCHAR|MTYPE_COUNTED_ARRAY: case MTYPE_UCHAR|MTYPE_STATIC_ARRAY: (*Size) += (cnt * sizeof(UCHAR)); break; default: status = STATUS_DATA_ERROR; break; }; if(!NT_SUCCESS(status)) break; } try_exit: NOTHING; } finally { if(AbnormalTermination()) { DfsDbgTrace(0, Dbg, "DfsRtlSize: Abnormal Termination!\n", 0); status = STATUS_DATA_ERROR; } } DfsDbgTrace(0, Dbg, "DfsRtlSize: (*Size) = %ld\n", (*Size)); DfsDbgTrace(-1, Dbg, "DfsRtlSize: Exit -> %08lx\n", status); return status; } VOID DfsRtlUnwindGet( IN PMARSHAL_INFO MarshalInfo, IN PMARSHAL_TYPE_INFO LastTypeInfo, IN PVOID Item ) { PMARSHAL_TYPE_INFO typeInfo; PVOID subItem; PVOID subItemElem; ULONG cnt; PUCHAR cntptr; ULONG itemSize; PMARSHAL_INFO subInfo; NTSTATUS status = STATUS_SUCCESS; DfsDbgTrace(+1, Dbg, "DfsRtlUnwindGet: Entered\n", 0); for(typeInfo = &MarshalInfo->_typeInfo[0]; typeInfo < LastTypeInfo; typeInfo++) { switch(typeInfo->_type & MTYPE_BASE_TYPE) { case MTYPE_COMPOUND: subInfo = typeInfo->_subinfo; itemSize = subInfo->_size; break; case MTYPE_GUID: itemSize = sizeof(GUID); break; case MTYPE_STRING: itemSize = sizeof(STRING); break; case MTYPE_UNICODE_STRING: itemSize = sizeof(UNICODE_STRING); break; case MTYPE_ULONG: itemSize = sizeof(ULONG); break; case MTYPE_USHORT: itemSize = sizeof(USHORT); break; case MTYPE_UCHAR: itemSize = sizeof(UCHAR); break; default: ExRaiseStatus(STATUS_DATA_ERROR); } if(typeInfo->_type & MTYPE_COUNTED_ARRAY) { cntptr = ((PUCHAR)Item + typeInfo->_cntoff); switch(typeInfo->_cntsize) { case sizeof(UCHAR): cnt = *(PUCHAR)cntptr; break; case sizeof(USHORT): cnt = *(PUSHORT)cntptr; break; case sizeof(ULONG): cnt = *(PULONG)cntptr; break; default: ExRaiseStatus(STATUS_DATA_ERROR); } } else cnt = typeInfo->_cntoff; if(typeInfo->_type & MTYPE_INDIRECT) { subItem = *(PUCHAR *)((PUCHAR)Item + typeInfo->_off); if(subItem == NULL && !((typeInfo->_type & MTYPE_COUNTED_ARRAY) && cnt == 0)) ExRaiseStatus(STATUS_DATA_ERROR); } else subItem = ((PUCHAR)Item + typeInfo->_off); switch(typeInfo->_type & ~MTYPE_INDIRECT) { case MTYPE_COMPOUND: DfsRtlUnwindGet( subInfo, &subInfo->_typeInfo[subInfo->_typecnt], subItem ); break; case (MTYPE_COMPOUND|MTYPE_COUNTED_ARRAY): case (MTYPE_COMPOUND|MTYPE_STATIC_ARRAY): subItemElem = (PUCHAR)subItem; while(cnt--) { DfsRtlUnwindGet( subInfo, &subInfo->_typeInfo[subInfo->_typecnt], subItemElem ); ((PUCHAR)subItemElem) += itemSize; } break; case MTYPE_STRING: DfsRtlUnwindStringGet((PSTRING)subItem); break; case MTYPE_UNICODE_STRING: DfsRtlUnwindUnicodeStringGet((PUNICODE_STRING)subItem); break; case (MTYPE_UNICODE_STRING|MTYPE_COUNTED_ARRAY): case (MTYPE_UNICODE_STRING|MTYPE_STATIC_ARRAY): subItemElem = (PUCHAR)subItem; while(cnt--) { DfsRtlUnwindUnicodeStringGet((PUNICODE_STRING)subItemElem); ((PUCHAR)subItemElem) += itemSize; } break; case MTYPE_GUID: case MTYPE_ULONG: case MTYPE_USHORT: case MTYPE_UCHAR: break; default: ExRaiseStatus(STATUS_DATA_ERROR); }; if(typeInfo->_type & MTYPE_INDIRECT) { MarshalBufferFree(subItem); *(PUCHAR *)((PUCHAR)Item + typeInfo->_off) = NULL; } } DfsDbgTrace(-1, Dbg, "DfsRtlUnwindGet: Exit -> VOID\n", 0); }