static NTSTATUS SrvShareBootstrapDiskRoot( IN OUT PLWIO_SRV_SHARE_ENTRY_LIST pShareList ) { NTSTATUS ntStatus = STATUS_SUCCESS; wchar16_t wszFileRootName[] = {'C','$',0}; PSTR pszDefaultSharePath = NULL; PWSTR pwszFileSystemRoot = NULL; PSRV_SHARE_INFO pShareInfo = NULL; ntStatus = SrvShareFindByName( pShareList, &wszFileRootName[0], &pShareInfo); if (ntStatus == STATUS_NOT_FOUND) { wchar16_t wszDesc[] = {'D','e','f','a','u','l','t',' ','S','h','a','r','e',0}; wchar16_t wszServiceType[] = LWIO_SRV_SHARE_STRING_ID_DISK_W; ntStatus = SrvGetDefaultSharePath(&pszDefaultSharePath); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvMbsToWc16s(pszDefaultSharePath, &pwszFileSystemRoot); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvCreateDefaultSharePath(pwszFileSystemRoot); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareAdd( pShareList, &wszFileRootName[0], pwszFileSystemRoot, &wszDesc[0], NULL, 0, &wszServiceType[0], 0); } BAIL_ON_NT_STATUS(ntStatus); cleanup: SRV_SAFE_FREE_MEMORY(pszDefaultSharePath); SRV_SAFE_FREE_MEMORY(pwszFileSystemRoot); return ntStatus; error: LWIO_LOG_ERROR("Failed to bootstrap default shares. [error code: %d]", ntStatus); goto cleanup; }
static VOID SrvSession2Free( PLWIO_SRV_SESSION_2 pSession ) { LWIO_LOG_DEBUG("Freeing session [object:0x%x][uid:%u]", pSession, pSession->ullUid); if (pSession->pMutex) { pthread_rwlock_destroy(&pSession->mutex); pSession->pMutex = NULL; } if (pSession->pTreeCollection) { LwRtlRBTreeFree(pSession->pTreeCollection); } if (pSession->hFinderRepository) { SrvFinderCloseRepository(pSession->hFinderRepository); } SRV_SAFE_FREE_MEMORY(pSession->pwszClientPrincipalName); if (pSession->pIoSecurityContext) { IoSecurityDereferenceSecurityContext(&pSession->pIoSecurityContext); } SrvFreeMemory(pSession); }
NTSTATUS SrvMatchPathPrefix( PWSTR pwszPath, ULONG ulPathLength, PWSTR pwszPrefix ) { NTSTATUS ntStatus = STATUS_NO_MATCH; ULONG ulPrefixLength = wc16slen(pwszPrefix); PWSTR pwszTmp = NULL; if (ulPathLength >= ulPrefixLength) { ntStatus = SrvAllocateMemory( (ulPrefixLength + 1) * sizeof(wchar16_t), (PVOID*)&pwszTmp); BAIL_ON_NT_STATUS(ntStatus); memcpy( (PBYTE)pwszTmp, (PBYTE)pwszPath, ulPrefixLength * sizeof(wchar16_t)); if (!SMBWc16sCaseCmp(pwszTmp, pwszPrefix)) { ntStatus = STATUS_SUCCESS; } } error: SRV_SAFE_FREE_MEMORY(pwszTmp); return ntStatus; }
NTSTATUS SrvSession2SetPrincipalName( PLWIO_SRV_SESSION_2 pSession, PCSTR pszClientPrincipal ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pSession->mutex); if (!pszClientPrincipal) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } SRV_SAFE_FREE_MEMORY(pSession->pwszClientPrincipalName); ntStatus = SMBMbsToWc16s( pszClientPrincipal, &pSession->pwszClientPrincipalName); BAIL_ON_NT_STATUS(ntStatus); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return ntStatus; error: goto cleanup; }
NTSTATUS SrvSocketGetAddrInfoW( PCWSTR pwszClientname, struct addrinfo** ppAddrInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; struct addrinfo* pAddrInfo = NULL; PSTR pszClientname = NULL; ntStatus = SrvWc16sToMbs(pwszClientname, &pszClientname); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvSocketGetAddrInfoA(pszClientname, &pAddrInfo); BAIL_ON_NT_STATUS(ntStatus); *ppAddrInfo = pAddrInfo; cleanup: SRV_SAFE_FREE_MEMORY(pszClientname); return ntStatus; error: *ppAddrInfo = NULL; if (pAddrInfo) { freeaddrinfo(pAddrInfo); } goto cleanup; }
NTSTATUS SrvShareDbBeginEnum( HANDLE hRepository, ULONG ulLimit, PHANDLE phResume ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_SHARE_DB_ENUM_CONTEXT pEnumContext = NULL; ntStatus = SrvAllocateMemory( sizeof(SRV_SHARE_DB_ENUM_CONTEXT), (PVOID*)&pEnumContext); BAIL_ON_NT_STATUS(ntStatus); pEnumContext->ulOffset = 0; pEnumContext->ulLimit = ulLimit; *phResume = (HANDLE)pEnumContext; cleanup: return ntStatus; error: *phResume = NULL; SRV_SAFE_FREE_MEMORY(pEnumContext); goto cleanup; }
static VOID SrvLogEchoState_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PECHO_REQUEST_HEADER pEchoHeader = NULL; // Do not Free PBYTE pEchoBlob = NULL; // Do Not Free PSTR pszHexString = NULL; ULONG ulLen = 0; va_list msgList; va_start(msgList, ulLine); pEchoHeader = va_arg(msgList, PECHO_REQUEST_HEADER); pEchoBlob = va_arg(msgList, PBYTE); if (pEchoHeader) { if (pEchoHeader->byteCount) { ntStatus = SrvGetHexDump( pEchoBlob, pEchoHeader->byteCount, SrvLogContextGetMaxLogLength(pLogContext), &pszHexString, &ulLen); BAIL_ON_NT_STATUS(ntStatus); } LW_RTL_LOG_RAW( logLevel, "srv", pszFunction, pszFile, ulLine, "Delete directory state: EchoCount(%u),EchoBlob[%u/%u bytes](%s)", pEchoHeader->echoCount, ulLen, pEchoHeader->byteCount, LWIO_SAFE_LOG_STRING(pszHexString)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszHexString); return; }
static VOID SrvLogOpenState_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_OPEN_STATE_SMB_V1 pOpenState = NULL; PSTR pszPath = NULL; va_list msgList; va_start(msgList, ulLine); pOpenState = va_arg(msgList, PSRV_OPEN_STATE_SMB_V1); if (pOpenState) { ntStatus = SrvUnicodeStringToMbs( &pOpenState->pFilename->Name, &pszPath); BAIL_ON_NT_STATUS(ntStatus); LW_RTL_LOG_RAW( logLevel, "srv", pszFunction, pszFile, ulLine, "Open state: " "alloc-size(%u),creation-time(0x%x),desired-access(0x%x)," "file-attrs(0x%x),flags(0x%x),open-function(%u)," "search-attrs(0x%x),path(%s)", pOpenState->pRequestHeader->ulAllocationSize, pOpenState->pRequestHeader->ulCreationTime, pOpenState->pRequestHeader->usDesiredAccess, pOpenState->pRequestHeader->usFileAttributes, pOpenState->pRequestHeader->usFlags, pOpenState->pRequestHeader->usOpenFunction, pOpenState->pRequestHeader->usSearchAttributes, LWIO_SAFE_LOG_STRING(pszPath)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszPath); return; }
NTSTATUS SrvShareRegEndEnum( IN HANDLE hRepository, IN HANDLE hResume ) { PSRV_SHARE_REG_ENUM_CONTEXT pEnumContext = (PSRV_SHARE_REG_ENUM_CONTEXT)hResume; SRV_SAFE_FREE_MEMORY(pEnumContext); return STATUS_SUCCESS; }
VOID SrvLogRequest_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_EXEC_CONTEXT pExecContext = NULL; PSTR pszBuffer = NULL; ULONG ulLen = 0; va_list msgList; va_start(msgList, ulLine); pExecContext = va_arg(msgList, PSRV_EXEC_CONTEXT); if (pExecContext) { ntStatus = SrvGetHexDump( (PBYTE)pExecContext->pSmbRequest->pSMBHeader, pExecContext->pSmbRequest->bufferUsed - sizeof(NETBIOS_HEADER), SrvLogContextGetMaxLogLength(pLogContext), &pszBuffer, &ulLen); BAIL_ON_NT_STATUS(ntStatus); LW_RTL_LOG_RAW( logLevel, "srv", pszFunction, pszFile, ulLine, "SMB Request:[%u/%u bytes][%s]", ulLen, pExecContext->pSmbRequest->bufferUsed - sizeof(NETBIOS_HEADER), LWIO_SAFE_LOG_STRING(pszBuffer)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszBuffer); }
static VOID SrvLogDeleteState_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_DELETE_STATE_SMB_V1 pDeleteState = NULL; PSTR pszSearchPattern = NULL; va_list msgList; va_start(msgList, ulLine); pDeleteState = va_arg(msgList, PSRV_DELETE_STATE_SMB_V1); if (pDeleteState) { if (pDeleteState->pwszSearchPattern) { ntStatus = SrvWc16sToMbs(pDeleteState->pwszSearchPattern, &pszSearchPattern); BAIL_ON_NT_STATUS(ntStatus); } LW_RTL_LOG_RAW( logLevel, "srv", pszFunction, pszFile, ulLine, "Delete directory state: SearchAttrs(0x%x),UseLongFilenames(%s),SearchPattern(%s)", pDeleteState->pRequestHeader->usSearchAttributes, pDeleteState->bUseLongFilenames ? "TRUE" : "FALSE", LWIO_SAFE_LOG_STRING(pszSearchPattern)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszSearchPattern); return; }
static VOID SrvLogCheckDirState_SMB_V1( PSRV_LOG_CONTEXT pLogContext, LWIO_LOG_LEVEL logLevel, PCSTR pszFunction, PCSTR pszFile, ULONG ulLine, ... ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_CHECKDIR_STATE_SMB_V1 pCheckdirState = NULL; PSTR pszPath = NULL; va_list msgList; va_start(msgList, ulLine); pCheckdirState = va_arg(msgList, PSRV_CHECKDIR_STATE_SMB_V1); if (pCheckdirState) { if (pCheckdirState->pwszPathFragment) { ntStatus = SrvWc16sToMbs(pCheckdirState->pwszPathFragment, &pszPath); BAIL_ON_NT_STATUS(ntStatus); } LW_RTL_LOG_RAW( logLevel, "lwio", pszFunction, pszFile, ulLine, "Check directory state: Path(%s)", LWIO_SAFE_LOG_STRING(pszPath)); } error: va_end(msgList); SRV_SAFE_FREE_MEMORY(pszPath); return; }
NTSTATUS SrvShareDbDelete( IN HANDLE hRepository, IN PWSTR pwszShareName ) { NTSTATUS ntStatus = 0; PSRV_SHARE_DB_CONTEXT pDbContext = (PSRV_SHARE_DB_CONTEXT)hRepository; PSTR pszShareName = NULL; BOOLEAN bInLock = FALSE; if (IsNullOrEmptyString(pwszShareName)) { ntStatus = STATUS_INVALID_PARAMETER_3; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvWc16sToMbs(pwszShareName, &pszShareName); BAIL_ON_NT_STATUS(ntStatus); LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gShareRepository_lwshare.dbMutex); if (!pDbContext->pDeleteStmt) { PCSTR pszQueryTemplate = "DELETE FROM " LWIO_SRV_SHARES_DB_TABLE_NAME \ " WHERE UPPER(" LWIO_SRV_SHARES_DB_COL_NAME ") = UPPER(?1)"; ntStatus = sqlite3_prepare_v2( pDbContext->pDbHandle, pszQueryTemplate, -1, &pDbContext->pDeleteStmt, NULL); BAIL_ON_LWIO_SRV_SQLITE_ERROR_DB(ntStatus, pDbContext->pDbHandle); } ntStatus = sqlite3_bind_text( pDbContext->pDeleteStmt, 1, pszShareName, -1, SQLITE_TRANSIENT); BAIL_ON_LWIO_SRV_SQLITE_ERROR_STMT(ntStatus, pDbContext->pDeleteStmt); if ((ntStatus = sqlite3_step(pDbContext->pDeleteStmt)) == SQLITE_DONE) { ntStatus = STATUS_SUCCESS; } BAIL_ON_LWIO_SRV_SQLITE_ERROR_STMT(ntStatus, pDbContext->pDeleteStmt); cleanup: if (pDbContext) { if (pDbContext->pDeleteStmt) { sqlite3_reset(pDbContext->pDeleteStmt); } } LWIO_UNLOCK_RWMUTEX(bInLock, &gShareRepository_lwshare.dbMutex); SRV_SAFE_FREE_MEMORY(pszShareName); return ntStatus; error: goto cleanup; }
static NTSTATUS SrvShareDbWriteToShareInfo( IN sqlite3_stmt* pSqlStatement, OUT PSRV_SHARE_INFO** pppShareInfoList, IN OUT PULONG pulNumSharesFound ) { NTSTATUS ntStatus = 0; PSRV_SHARE_INFO* ppShareInfoList = NULL; PSRV_SHARE_INFO pShareInfo = NULL; PWSTR pwszStringVal = NULL; ULONG ulIntVal = 0; ULONG ulNumSharesAllocated = 0; ULONG ulNumSharesAvailable = 0; ULONG iShare = 0; while ((ntStatus = sqlite3_step(pSqlStatement)) == SQLITE_ROW) { ULONG iCol = 0; if (!ulNumSharesAvailable) { PSRV_SHARE_INFO* ppShareInfoListNew = NULL; ULONG ulNumSharesNew = 5; ULONG ulNumSharesAllocatedNew = ulNumSharesAllocated + ulNumSharesNew; ntStatus = SrvAllocateMemory( sizeof(PSRV_SHARE_INFO) * ulNumSharesAllocatedNew, (PVOID*)&ppShareInfoListNew); BAIL_ON_NT_STATUS(ntStatus); if (ppShareInfoList) { memcpy((PBYTE)ppShareInfoListNew, (PBYTE)ppShareInfoList, sizeof(PSRV_SHARE_INFO) * ulNumSharesAllocated); SrvFreeMemory(ppShareInfoList); } ppShareInfoList = ppShareInfoListNew; ulNumSharesAllocated = ulNumSharesAllocatedNew; ulNumSharesAvailable = ulNumSharesNew; } ntStatus = SrvAllocateMemory( sizeof(SRV_SHARE_INFO), (PVOID*)&pShareInfo); BAIL_ON_NT_STATUS(ntStatus); pShareInfo->refcount = 1; pthread_rwlock_init(&pShareInfo->mutex, NULL); pShareInfo->pMutex = &pShareInfo->mutex; for (; iCol < 5; iCol++) { const unsigned char* pszStringVal = NULL; ULONG ulNumBytes = sqlite3_column_bytes(pSqlStatement, iCol); switch(iCol) { case 0: /* ShareName */ if (ulNumBytes) { pszStringVal = sqlite3_column_text(pSqlStatement, iCol); ntStatus = SrvMbsToWc16s( (PCSTR)pszStringVal, &pShareInfo->pwszName); BAIL_ON_NT_STATUS(ntStatus); } break; case 1: /* PathName */ if (ulNumBytes) { pszStringVal = sqlite3_column_text(pSqlStatement, iCol); ntStatus = SrvMbsToWc16s( (PCSTR)pszStringVal, &pShareInfo->pwszPath); BAIL_ON_NT_STATUS(ntStatus); } break; case 2: /* Comment */ if (ulNumBytes) { pszStringVal = sqlite3_column_text(pSqlStatement, iCol); ntStatus = SrvMbsToWc16s( (PCSTR)pszStringVal, &pShareInfo->pwszComment); } else { /* Deal with empty comments */ ntStatus = SrvMbsToWc16s( "", &pShareInfo->pwszComment); } BAIL_ON_NT_STATUS(ntStatus); break; case 3: /* Security Descriptor */ if (ulNumBytes) { PCVOID pBlob = sqlite3_column_blob(pSqlStatement, iCol); ntStatus = SrvAllocateMemory( ulNumBytes, (PVOID*)&pShareInfo->pSecDesc); BAIL_ON_NT_STATUS(ntStatus); memcpy(pShareInfo->pSecDesc, pBlob, ulNumBytes); pShareInfo->ulSecDescLen = ulNumBytes; } break; case 4: /* service */ if (ulNumBytes) { pszStringVal = sqlite3_column_text(pSqlStatement, iCol); } ntStatus = SrvMbsToWc16s( (PCSTR)pszStringVal, &pwszStringVal); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareMapServiceStringToId( pwszStringVal, &pShareInfo->service); BAIL_ON_NT_STATUS(ntStatus); break; case 5: /* flags */ if (ulNumBytes) { ulIntVal = sqlite3_column_int(pSqlStatement, iCol); } pShareInfo->ulFlags = ulIntVal; break; } } *(ppShareInfoList + iShare++) = pShareInfo; pShareInfo = NULL; ulNumSharesAvailable--; } if (ntStatus == SQLITE_DONE) { ntStatus = STATUS_SUCCESS; } BAIL_ON_LWIO_SRV_SQLITE_ERROR_STMT(ntStatus, pSqlStatement); *pppShareInfoList = ppShareInfoList; *pulNumSharesFound = iShare; cleanup: SRV_SAFE_FREE_MEMORY(pwszStringVal); if (pShareInfo) { SrvShareReleaseInfo(pShareInfo); } return ntStatus; error: *pppShareInfoList = NULL; *pulNumSharesFound = 0; if (ppShareInfoList) { SrvShareFreeInfoList(ppShareInfoList, iShare); } goto cleanup; }
NTSTATUS SrvShareDbAdd( IN HANDLE hRepository, IN PWSTR pwszShareName, IN PWSTR pwszPath, IN PWSTR pwszComment, IN PBYTE pSecDesc, IN ULONG ulSecDescLen, IN PWSTR pwszService, IN ULONG ulFlags ) { NTSTATUS ntStatus = 0; PSRV_SHARE_DB_CONTEXT pDbContext = NULL; PSTR pszShareName = NULL; PSTR pszPath = NULL; PSTR pszComment = NULL; PSTR pszService = NULL; BOOLEAN bInLock = FALSE; if (pwszShareName) { ntStatus = SrvWc16sToMbs(pwszShareName, &pszShareName); BAIL_ON_NT_STATUS(ntStatus); } if (pwszPath) { ntStatus = SrvWc16sToMbs(pwszPath, &pszPath); BAIL_ON_NT_STATUS(ntStatus); } if (pwszComment) { ntStatus = SrvWc16sToMbs(pwszComment, &pszComment); BAIL_ON_NT_STATUS(ntStatus); } if (pwszService) { ntStatus = SrvWc16sToMbs(pwszService, &pszService); BAIL_ON_NT_STATUS(ntStatus); } LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gShareRepository_lwshare.dbMutex); pDbContext = (PSRV_SHARE_DB_CONTEXT)hRepository; ntStatus = SrvShareDbAdd_inlock( pDbContext, pszShareName, pszPath, pszComment, pSecDesc, ulSecDescLen, pszService, ulFlags); BAIL_ON_NT_STATUS(ntStatus); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &gShareRepository_lwshare.dbMutex); SRV_SAFE_FREE_MEMORY(pszShareName); SRV_SAFE_FREE_MEMORY(pszPath); SRV_SAFE_FREE_MEMORY(pszComment); SRV_SAFE_FREE_MEMORY(pszService); return ntStatus; error: goto cleanup; }
NTSTATUS SrvShareDbFindByName( HANDLE hRepository, PWSTR pwszShareName, PSRV_SHARE_INFO* ppShareInfo ) { NTSTATUS ntStatus = 0; PSRV_SHARE_INFO* ppShareInfoList = NULL; PSTR pszShareName = NULL; BOOLEAN bInLock = FALSE; ULONG ulNumSharesFound = 0; PSRV_SHARE_DB_CONTEXT pDbContext = NULL; if (IsNullOrEmptyString(pwszShareName)) { ntStatus = STATUS_INVALID_PARAMETER_2; } BAIL_ON_NT_STATUS(ntStatus); pDbContext = (PSRV_SHARE_DB_CONTEXT)hRepository; ntStatus = SrvWc16sToMbs(pwszShareName, &pszShareName); BAIL_ON_NT_STATUS(ntStatus); if (!pDbContext->pFindStmt) { PCSTR pszQueryTemplate = "SELECT " LWIO_SRV_SHARES_DB_COL_NAME "," \ LWIO_SRV_SHARES_DB_COL_PATH "," \ LWIO_SRV_SHARES_DB_COL_COMMENT "," \ LWIO_SRV_SHARES_DB_COL_SECDESC "," \ LWIO_SRV_SHARES_DB_COL_SERVICE \ " FROM " LWIO_SRV_SHARES_DB_TABLE_NAME \ " WHERE UPPER(" LWIO_SRV_SHARES_DB_COL_NAME ") = UPPER(?1)"; ntStatus = sqlite3_prepare_v2( pDbContext->pDbHandle, pszQueryTemplate, -1, &pDbContext->pFindStmt, NULL); BAIL_ON_LWIO_SRV_SQLITE_ERROR_DB(ntStatus, pDbContext->pDbHandle); } ntStatus = sqlite3_bind_text( pDbContext->pFindStmt, 1, pszShareName, -1, SQLITE_TRANSIENT); BAIL_ON_LWIO_SRV_SQLITE_ERROR_STMT(ntStatus, pDbContext->pFindStmt); LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gShareRepository_lwshare.dbMutex); ntStatus = SrvShareDbWriteToShareInfo( pDbContext->pFindStmt, &ppShareInfoList, &ulNumSharesFound); BAIL_ON_NT_STATUS(ntStatus); *ppShareInfo = *ppShareInfoList; cleanup: if (pDbContext) { if (pDbContext->pFindStmt) { sqlite3_reset(pDbContext->pFindStmt); } } LWIO_UNLOCK_RWMUTEX(bInLock, &gShareRepository_lwshare.dbMutex); if (ppShareInfoList) { SrvShareFreeInfoList(ppShareInfoList, ulNumSharesFound); } SRV_SAFE_FREE_MEMORY(pszShareName); return ntStatus; error: *ppShareInfo = NULL; goto cleanup; }
static NTSTATUS SrvShareRegWriteToShareInfo( IN REG_DATA_TYPE regDataType, IN PWSTR pwszShareName, IN PBYTE pData, IN ULONG ulDataLen, IN REG_DATA_TYPE regSecDataType, IN PBYTE pSecData, IN ULONG ulSecDataLen, OUT PSRV_SHARE_INFO* ppShareInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_SHARE_INFO pShareInfo = NULL; PWSTR* ppwszValues = NULL; PSTR pszFlags = NULL; ntStatus = SrvAllocateMemory(sizeof(*pShareInfo), (PVOID*)&pShareInfo); BAIL_ON_NT_STATUS(ntStatus); pShareInfo->refcount = 1; pthread_rwlock_init(&pShareInfo->mutex, NULL); pShareInfo->pMutex = &pShareInfo->mutex; ntStatus = SrvAllocateStringW(pwszShareName, &pShareInfo->pwszName); BAIL_ON_NT_STATUS(ntStatus); if (pData) { ULONG iValue = 0; wchar16_t wszCommentPrefix[] = REG_KEY_COMMENT_PREFIX_W; ULONG ulCommentPrefixLen = (sizeof(wszCommentPrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszPathPrefix[] = REG_KEY_PATH_PREFIX_W; ULONG ulPathPrefixLen = (sizeof(wszPathPrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszServicePrefix[] = REG_KEY_SERVICE_PREFIX_W; ULONG ulServicePrefixLen = (sizeof(wszServicePrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszFlagsPrefix[] = REG_KEY_FLAGS_PREFIX_W; ULONG ulFlagsPrefixLen = (sizeof(wszFlagsPrefix)/sizeof(wchar16_t)) - 1; ntStatus = NtRegByteArrayToMultiStrs(pData, ulDataLen, &ppwszValues); BAIL_ON_NT_STATUS(ntStatus); for (; ppwszValues[iValue]; iValue++) { PWSTR pwszValue = &ppwszValues[iValue][0]; if (!wc16sncmp(&wszPathPrefix[0], pwszValue, ulPathPrefixLen)) { SRV_SAFE_FREE_MEMORY(pShareInfo->pwszPath); ntStatus = SrvAllocateStringW( &pwszValue[ulPathPrefixLen], &pShareInfo->pwszPath); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszCommentPrefix[0], pwszValue, ulCommentPrefixLen)) { SRV_SAFE_FREE_MEMORY(pShareInfo->pwszComment); ntStatus = SrvAllocateStringW( &pwszValue[ulCommentPrefixLen], &pShareInfo->pwszComment); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszServicePrefix[0], pwszValue, ulServicePrefixLen)) { ntStatus = SrvShareMapServiceStringToIdW( &pwszValue[ulServicePrefixLen], &pShareInfo->service); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszFlagsPrefix[0], pwszValue, ulFlagsPrefixLen)) { ntStatus = RtlCStringAllocateFromWC16String( &pszFlags, &pwszValue[ulFlagsPrefixLen]); BAIL_ON_NT_STATUS(ntStatus); pShareInfo->ulFlags = strtol(pszFlags, NULL, 16); } else { ntStatus = STATUS_INVALID_PARAMETER_3; BAIL_ON_NT_STATUS(ntStatus); } } } if (!pShareInfo->pwszComment) { wchar16_t wszComment[] = {0}; ntStatus = SrvAllocateStringW( &wszComment[0], &pShareInfo->pwszComment); BAIL_ON_NT_STATUS(ntStatus); } if (ulSecDataLen) { ntStatus = SrvShareSetSecurity( pShareInfo, (PSECURITY_DESCRIPTOR_RELATIVE)pSecData, ulSecDataLen); BAIL_ON_NT_STATUS(ntStatus); } else { ntStatus = SrvShareSetDefaultSecurity(pShareInfo); BAIL_ON_NT_STATUS(ntStatus); } *ppShareInfo = pShareInfo; cleanup: if (ppwszValues) { RegFreeMultiStrsW(ppwszValues); } RTL_FREE(&pszFlags); return ntStatus; error: if (pShareInfo) { SrvShareReleaseInfo(pShareInfo); } goto cleanup; }
NTSTATUS SrvBuildNegotiateResponse_SMB_V1_NTLM_0_12( IN PLWIO_SRV_CONNECTION pConnection, IN PSMB_PACKET pSmbRequest, IN SMB_PROTOCOL_DIALECT Dialect, IN USHORT idxDialect, OUT PSMB_PACKET* ppSmbResponse ) { NTSTATUS ntStatus = 0; NEGOTIATE_RESPONSE_HEADER* pResponseHeader = NULL; time_t curTime = 0L; LONG64 llUTCTime = 0LL; uint16_t byteCount = 0; uint8_t* pDataCursor = NULL; PSRV_PROPERTIES pServerProperties = &pConnection->serverProperties; PSMB_PACKET pSmbResponse = NULL; PWSTR pwszHostname = NULL; ntStatus = SMBPacketAllocate( pConnection->hPacketAllocator, &pSmbResponse); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SMBPacketBufferAllocate( pConnection->hPacketAllocator, (64 * 1024) + 4096, &pSmbResponse->pRawBuffer, &pSmbResponse->bufferLen); BAIL_ON_NT_STATUS(ntStatus); if ((pSmbRequest->pSMBHeader->flags2 & FLAG2_EXT_SEC) == 0) { pServerProperties->Capabilities &= ~CAP_EXTENDED_SECURITY; } ntStatus = SMBPacketMarshallHeader( pSmbResponse->pRawBuffer, pSmbResponse->bufferLen, COM_NEGOTIATE, 0, TRUE, pSmbRequest->pSMBHeader->tid, SMB_V1_GET_PROCESS_ID(pSmbRequest->pSMBHeader), 0, pSmbRequest->pSMBHeader->mid, FALSE, pSmbResponse); BAIL_ON_NT_STATUS(ntStatus); if ((pServerProperties->Capabilities & CAP_EXTENDED_SECURITY) == 0) { pSmbResponse->pSMBHeader->flags2 &= ~FLAG2_EXT_SEC; } pSmbResponse->pSMBHeader->wordCount = 17; pResponseHeader = (NEGOTIATE_RESPONSE_HEADER*)pSmbResponse->pParams; pSmbResponse->pData = pSmbResponse->pParams + sizeof(NEGOTIATE_RESPONSE_HEADER); pSmbResponse->bufferUsed += sizeof(NEGOTIATE_RESPONSE_HEADER); pResponseHeader->dialectIndex = idxDialect; pResponseHeader->securityMode = 0; if (pServerProperties->preferredSecurityMode == SMB_SECURITY_MODE_USER) { pResponseHeader->securityMode |= 0x1; // User level security } if (pServerProperties->bEncryptPasswords) { pResponseHeader->securityMode |= 0x2; } if (pServerProperties->bEnableSecuritySignatures) { pResponseHeader->securityMode |= 0x4; } if (pServerProperties->bRequireSecuritySignatures) { pResponseHeader->securityMode |= 0x8; } pResponseHeader->maxMpxCount = pServerProperties->MaxMpxCount; pResponseHeader->maxNumberVcs = pServerProperties->MaxNumberVCs; pResponseHeader->maxBufferSize = pServerProperties->MaxBufferSize; pResponseHeader->maxRawSize = pServerProperties->MaxRawSize; pResponseHeader->sessionKey = 0; pResponseHeader->capabilities = pServerProperties->Capabilities; curTime = time(NULL); ntStatus = WireSMBUTimeToTimeZone(curTime, &pResponseHeader->serverTimeZone); BAIL_ON_NT_STATUS(ntStatus); ntStatus = WireSMBUTimetoNTTime(curTime, FALSE, &llUTCTime); BAIL_ON_NT_STATUS(ntStatus); pResponseHeader->systemTimeLow = llUTCTime & 0xFFFFFFFFLL; pResponseHeader->systemTimeHigh = (llUTCTime & 0xFFFFFFFF00000000LL) >> 32; pDataCursor = pSmbResponse->pData; if (pResponseHeader->capabilities & CAP_EXTENDED_SECURITY) { PBYTE pNegHintsBlob = NULL; /* Do not free */ ULONG ulNegHintsLength = 0; pResponseHeader->encryptionKeyLength = 0; memcpy(pDataCursor, pServerProperties->GUID, sizeof(pServerProperties->GUID)); pDataCursor += sizeof(pServerProperties->GUID); byteCount += sizeof(pServerProperties->GUID); ntStatus = SrvGssNegHints(&pNegHintsBlob, &ulNegHintsLength); /* Microsoft clients ignore the security blob on the neg prot response so don't fail here if we can't get a negHintsBlob */ if (ntStatus == STATUS_SUCCESS) { memcpy(pDataCursor, pNegHintsBlob, ulNegHintsLength); pDataCursor += ulNegHintsLength; byteCount += ulNegHintsLength; } } else { WCHAR wszWorkgroup[] = SRV_NATIVE_DOMAIN_W; CHAR szHostname[HOST_NAME_MAX]; PWSTR pwszDomain = pConnection->clientProperties.pwszNativeDomain; if (!pwszDomain) { pwszDomain = &wszWorkgroup[0]; } if (gethostname(szHostname, HOST_NAME_MAX) == -1) { ntStatus = LwErrnoToNtStatus(errno); BAIL_ON_NT_STATUS(ntStatus); } pResponseHeader->encryptionKeyLength = sizeof(pConnection->ServerChallenge); // Generate challenge and remember it in connection if (!RAND_bytes( pConnection->ServerChallenge, sizeof(pConnection->ServerChallenge))) { ntStatus = STATUS_INTERNAL_ERROR; BAIL_ON_NT_STATUS(ntStatus); } RtlCopyMemory(pDataCursor, &pConnection->ServerChallenge, sizeof(pConnection->ServerChallenge)); pDataCursor += sizeof(pConnection->ServerChallenge); byteCount += sizeof(pConnection->ServerChallenge); // Add domain name { size_t sDomainLen = (wc16slen(pwszDomain)+1) * sizeof(wchar16_t); RtlCopyMemory(pDataCursor, pwszDomain, sDomainLen); pDataCursor += sDomainLen; byteCount += sDomainLen; } // Add hostname { size_t sHostnameLen = 0; ntStatus = SrvMbsToWc16s(szHostname, &pwszHostname); BAIL_ON_NT_STATUS(ntStatus); sHostnameLen = (wc16slen(pwszHostname)+1) * sizeof(wchar16_t); RtlCopyMemory(pDataCursor, pwszHostname, sHostnameLen); pDataCursor += sHostnameLen; byteCount += sHostnameLen; } } pResponseHeader->byteCount = byteCount; pSmbResponse->bufferUsed += byteCount; ntStatus = SMBPacketMarshallFooter(pSmbResponse); BAIL_ON_NT_STATUS(ntStatus); *ppSmbResponse = pSmbResponse; cleanup: SRV_SAFE_FREE_MEMORY(pwszHostname); return ntStatus; error: *ppSmbResponse = NULL; if (pSmbResponse) { SMBPacketRelease(pConnection->hPacketAllocator, pSmbResponse); } goto cleanup; }
static NTSTATUS SrvProtocolEnumCandidateConnections( PVOID pKey, PVOID pData, PVOID pUserData, PBOOLEAN pbContinue ) { NTSTATUS ntStatus = STATUS_SUCCESS; PLWIO_SRV_CONNECTION pConnection = (PLWIO_SRV_CONNECTION)pData; PSRV_PROTOCOL_CONNECTION_ENUM_QUERY pConnectionEnumQuery = (PSRV_PROTOCOL_CONNECTION_ENUM_QUERY)pUserData; BOOLEAN bInLock = FALSE; PWSTR pwszClientHost = NULL; if (pConnectionEnumQuery->pQueryAddress) { /* * Look for connections by computer address first in case * that was the qualifier string */ struct addrinfo* pCursor = pConnectionEnumQuery->pQueryAddress; BOOLEAN bMatch = FALSE; for (; !bMatch && (pCursor != NULL); pCursor = pCursor->ai_next) { ntStatus = SrvSocketCompareAddress( pConnection->pClientAddress, pConnection->clientAddrLen, pCursor->ai_addr, pCursor->ai_addrlen, &bMatch); BAIL_ON_NT_STATUS(ntStatus); } if (!bMatch) { pConnection = NULL; } } if (pConnection) { LWIO_LOCK_RWMUTEX_SHARED(bInLock, &pConnection->mutex); ntStatus = SrvSocketAddressToStringW(pConnection->pClientAddress, &pwszClientHost); BAIL_ON_NT_STATUS(ntStatus); pConnectionEnumQuery->pwszClientHost = pwszClientHost; pConnectionEnumQuery->pClientAddress = pConnection->pClientAddress; pConnectionEnumQuery->clientAddrLen = pConnection->clientAddrLen; pConnectionEnumQuery->ulConnectionResId = pConnection->resource.ulResourceId; ntStatus = WireGetCurrentNTTime(&pConnectionEnumQuery->llCurTime); BAIL_ON_NT_STATUS(ntStatus); switch (SrvConnectionGetProtocolVersion(pConnection)) { case SMB_PROTOCOL_VERSION_1: ntStatus = LwRtlRBTreeTraverse( pConnection->pSessionCollection, LWRTL_TREE_TRAVERSAL_TYPE_IN_ORDER, &SrvProtocolProcessCandidateConnection, pConnectionEnumQuery); break; case SMB_PROTOCOL_VERSION_2: ntStatus = LwRtlRBTreeTraverse( pConnection->pSessionCollection, LWRTL_TREE_TRAVERSAL_TYPE_IN_ORDER, &SrvProtocolProcessCandidateConnection2, pConnectionEnumQuery); break; case SMB_PROTOCOL_VERSION_UNKNOWN: /* Ignore connections that are still being established */ break; default: ntStatus = STATUS_INTERNAL_ERROR; break; } BAIL_ON_NT_STATUS(ntStatus); } *pbContinue = TRUE; cleanup: pConnectionEnumQuery->pClientAddress = NULL; pConnectionEnumQuery->clientAddrLen = 0; pConnectionEnumQuery->pwszClientHost = NULL; SRV_SAFE_FREE_MEMORY(pwszClientHost); LWIO_UNLOCK_RWMUTEX(bInLock, &pConnection->mutex); return ntStatus; error: *pbContinue = FALSE; goto cleanup; }
NTSTATUS SrvShareRegBeginEnum( HANDLE hRepository, ULONG ulBatchLimit, PHANDLE phResume ) { NTSTATUS ntStatus = 0; HKEY hRootKey = NULL; HKEY hKey = NULL; wchar16_t wszHKTM[] = HKEY_THIS_MACHINE_W; wchar16_t wszSharesKey[] = REG_KEY_PATH_SRV_SHARES_W; PSRV_SHARE_REG_ENUM_CONTEXT pEnumContext = NULL; if (!ulBatchLimit || (ulBatchLimit == UINT32_MAX)) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvAllocateMemory( sizeof(SRV_SHARE_REG_ENUM_CONTEXT), (PVOID*)&pEnumContext); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, NULL, &wszHKTM[0], 0, KEY_READ, &hRootKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, hRootKey, &wszSharesKey[0], 0, KEY_READ, &hKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegQueryInfoKeyW( hRepository, hKey, NULL, NULL, NULL, NULL, NULL, NULL, &pEnumContext->ulValuesAvailable, &pEnumContext->ulMaxValueNameLen, &pEnumContext->ulMaxValueLen, NULL, NULL); BAIL_ON_NT_STATUS(ntStatus); pEnumContext->ulBatchLimit = ulBatchLimit; *phResume = (HANDLE)pEnumContext; cleanup: if (hRootKey) { NtRegCloseKey(hRepository, hRootKey); } if (hKey) { NtRegCloseKey(hRepository, hKey); } return ntStatus; error: *phResume = NULL; SRV_SAFE_FREE_MEMORY(pEnumContext); goto cleanup; }
NTSTATUS SrvShareRegEnum( HANDLE hRepository, HANDLE hResume, PSRV_SHARE_INFO** pppShareInfoList, PULONG pulNumSharesFound ) { NTSTATUS ntStatus = 0; ULONG ulIndex = 0; ULONG ulBatchIndex = 0; HKEY hRootKey = NULL; HKEY hKey = NULL; HKEY hSecKey = NULL; PWSTR pwszValueName = NULL; PBYTE pData = NULL; REG_DATA_TYPE dataType = REG_UNKNOWN; wchar16_t wszHKTM[] = HKEY_THIS_MACHINE_W; wchar16_t wszSharesKey[] = REG_KEY_PATH_SRV_SHARES_W; wchar16_t wszShareSecKey[] = REG_KEY_PATH_SRV_SHARES_SECURITY_W; PSRV_SHARE_INFO* ppShareInfoList = NULL; REG_DATA_TYPE dataSecType = REG_UNKNOWN; ULONG ulNumSharesFound = 0; BYTE pSecData[MAX_VALUE_LENGTH] = {0}; PSRV_SHARE_REG_ENUM_CONTEXT pResume = (PSRV_SHARE_REG_ENUM_CONTEXT)hResume; if (!pResume) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NtRegOpenKeyExW( hRepository, NULL, &wszHKTM[0], 0, KEY_READ, &hRootKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, hRootKey, &wszSharesKey[0], 0, KEY_READ, &hKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExW( hRepository, hRootKey, &wszShareSecKey[0], 0, KEY_READ, &hSecKey); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvAllocateMemory( pResume->ulBatchLimit * sizeof(*ppShareInfoList), (PVOID) &ppShareInfoList); BAIL_ON_NT_STATUS(ntStatus); ulBatchIndex = pResume->ulBatchIndex; for (ulIndex = 0; ulIndex < pResume->ulBatchLimit; ulIndex++) { ULONG ulMaxValueNameLen = 0; ULONG ulMaxValueLen = 0; ULONG ulMaxSecValueLen = 0; ulMaxValueNameLen = (pResume->ulMaxValueNameLen + 1) * sizeof(*pwszValueName); ulMaxValueLen = pResume->ulMaxValueLen; ulMaxSecValueLen = MAX_VALUE_LENGTH; if (ulMaxValueNameLen) { SRV_SAFE_FREE_MEMORY_AND_RESET(pwszValueName); ntStatus = SrvAllocateMemory( ulMaxValueNameLen, (PVOID*) &pwszValueName); BAIL_ON_NT_STATUS(ntStatus); } if (ulMaxValueLen) { SRV_SAFE_FREE_MEMORY_AND_RESET(pData); ntStatus = SrvAllocateMemory(ulMaxValueLen, (PVOID*) &pData); BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NtRegEnumValueW( hRepository, hKey, ulBatchIndex++, pwszValueName, &ulMaxValueNameLen, NULL, &dataType, pData, &ulMaxValueLen); if (ntStatus == STATUS_NO_MORE_MATCHES || ntStatus == STATUS_NO_MORE_ENTRIES) { ntStatus = STATUS_SUCCESS; break; } BAIL_ON_NT_STATUS(ntStatus); if (REG_MULTI_SZ != dataType) { continue; } ntStatus = NtRegGetValueW( hRepository, hSecKey, NULL, pwszValueName, RRF_RT_REG_BINARY, &dataSecType, pSecData, &ulMaxSecValueLen); if (STATUS_OBJECT_NAME_NOT_FOUND == ntStatus) { ntStatus = 0; ulMaxSecValueLen = 0; } BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvShareRegWriteToShareInfo( dataType, pwszValueName, pData, ulMaxValueLen, dataSecType, pSecData, ulMaxSecValueLen, &ppShareInfoList[ulNumSharesFound++]); BAIL_ON_NT_STATUS(ntStatus); } pResume->ulBatchIndex = ulBatchIndex; *pppShareInfoList = ppShareInfoList; *pulNumSharesFound = ulNumSharesFound; cleanup: if (hRootKey) { NtRegCloseKey(hRepository, hRootKey); } if (hKey) { NtRegCloseKey(hRepository, hKey); } if (hSecKey) { NtRegCloseKey(hRepository, hSecKey); } SRV_SAFE_FREE_MEMORY(pwszValueName); SRV_SAFE_FREE_MEMORY(pData); return ntStatus; error: *pppShareInfoList = NULL; *pulNumSharesFound = 0; if (ppShareInfoList) { SrvShareFreeInfoList(ppShareInfoList, ulNumSharesFound); } goto cleanup; }
NTSTATUS SrvFinderBuildSearchPath( IN PWSTR pwszPath, IN PWSTR pwszSearchPattern, OUT PWSTR* ppwszFilesystemPath, OUT PWSTR* ppwszSearchPattern, IN OUT OPTIONAL PBOOLEAN pbPathHasWildCards ) { NTSTATUS ntStatus = 0; wchar16_t wszStar[] = {'*', 0}; wchar16_t wszBackslash[] = {'\\', 0}; wchar16_t wszQuestionMark[] = {'?', 0}; wchar16_t wszQuote[] = {'\"', 0}; wchar16_t wszGT[] = {'>', 0}; wchar16_t wszLT[] = {'<', 0}; wchar16_t wszDot[] = {'.', 0}; size_t sLen = 0; PWSTR pwszCursor = NULL; PWSTR pwszLastSlash = NULL; PWSTR pwszFilesystemPath = NULL; PWSTR pwszSearchPattern3 = NULL; PWSTR pwszSearchPattern2 = NULL; BOOLEAN bPathHasWildCards = FALSE; sLen = IsNullOrEmptyString(pwszPath) ? 0 : wc16slen(pwszPath); while (pwszSearchPattern && *pwszSearchPattern && (*pwszSearchPattern == wszBackslash[0])) { pwszSearchPattern++; } if (pwszSearchPattern && *pwszSearchPattern) { ntStatus = SrvAllocateStringW(pwszSearchPattern, &pwszSearchPattern3); BAIL_ON_NT_STATUS(ntStatus); } pwszCursor = pwszSearchPattern3; while (pwszCursor && *pwszCursor) { if (*pwszCursor == wszGT[0]) { bPathHasWildCards = TRUE; *pwszCursor = wszQuestionMark[0]; } else if (*pwszCursor == wszQuote[0]) { PWSTR pwszNext = pwszCursor; pwszNext++; if (!pwszNext || ((*pwszNext == wszQuestionMark[0] || *pwszNext == wszStar[0] || *pwszNext == wszGT[0] || *pwszNext == wszLT[0] || *pwszNext == wszQuote[0]))) { bPathHasWildCards = TRUE; *pwszCursor = wszDot[0]; } } else if (*pwszCursor == wszLT[0]) { PWSTR pwszNext = pwszCursor; bPathHasWildCards = TRUE; pwszNext++; if (pwszNext || (((*pwszNext == wszDot[0]) || (*pwszNext == wszQuote[0]) || (*pwszNext == wszLT[0])))) { *pwszCursor = wszStar[0]; } } pwszCursor++; } pwszCursor = pwszSearchPattern3; while (pwszCursor && *pwszCursor) { if (*pwszCursor == wszBackslash[0]) { pwszLastSlash = pwszCursor; } else if ((*pwszCursor == wszStar[0]) || (*pwszCursor == wszQuestionMark[0])) { bPathHasWildCards = TRUE; break; } pwszCursor++; } if (pwszLastSlash) { PBYTE pDataCursor = NULL; size_t sSuffixLen = 0; sSuffixLen = ((PBYTE)pwszLastSlash - (PBYTE)pwszSearchPattern3); ntStatus = SrvAllocateMemory( sLen * sizeof(wchar16_t) + sizeof(wszBackslash[0]) + sSuffixLen + sizeof(wchar16_t), (PVOID*)&pwszFilesystemPath); BAIL_ON_NT_STATUS(ntStatus); pDataCursor = (PBYTE)pwszFilesystemPath; if (sLen) { memcpy(pDataCursor, (PBYTE)pwszPath, sLen * sizeof(wchar16_t)); pDataCursor += sLen * sizeof(wchar16_t); } *((wchar16_t*)pDataCursor) = wszBackslash[0]; pDataCursor += sizeof(wszBackslash[0]); memcpy(pDataCursor, pwszSearchPattern, sSuffixLen); } else if (pwszPath) { ntStatus = SrvAllocateStringW( pwszPath, &pwszFilesystemPath); BAIL_ON_NT_STATUS(ntStatus); } pwszCursor = (pwszLastSlash ? ++pwszLastSlash : pwszSearchPattern3); if (pwszCursor && *pwszCursor) { ntStatus = SrvAllocateStringW(pwszCursor, &pwszSearchPattern2); } else { ntStatus = SrvAllocateStringW(wszStar, &pwszSearchPattern2); } BAIL_ON_NT_STATUS(ntStatus); *ppwszFilesystemPath = pwszFilesystemPath; *ppwszSearchPattern = pwszSearchPattern2; if (pbPathHasWildCards) { *pbPathHasWildCards = bPathHasWildCards; } cleanup: SRV_SAFE_FREE_MEMORY(pwszSearchPattern3); return ntStatus; error: *ppwszFilesystemPath = NULL; *ppwszSearchPattern = NULL; if (pbPathHasWildCards) { *pbPathHasWildCards = FALSE; } SRV_SAFE_FREE_MEMORY(pwszFilesystemPath); SRV_SAFE_FREE_MEMORY(pwszSearchPattern2); goto cleanup; }