diff --git a/README-NT b/README-NT index 5a4158a16c..15e8216dac 100644 --- a/README-NT +++ b/README-NT @@ -58,10 +58,12 @@ versions are supported: Microsoft Visual Studio .NET 2003 available via a MSDN subscription - Microsoft Visual Studio .NET 2005 (required for AMD64 builds) + Microsoft Visual Studio .NET 2005 available via a MSDN subscription (recommended - required for 64-bit builds) + Microsoft Visual Studio 2008 is not supported + The following Microsoft SDK is required: Microsoft Platform SDK for Windows XP SP2 or Server 2003 SP1 or Vista @@ -78,6 +80,10 @@ The Microsoft HTML Help Workshop is required: http://www.microsoft.com/downloads/details.aspx?familyid=00535334-c8a6-452f-9aa0-d597d16580cc&displaylang=en +The Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1 is required: + + http://www.microsoft.com/downloads/details.aspx?FamilyId=AD6158D7-DDBA-416A-9109-07607425A815&displaylang=en + The NSIS installer requires about 14 MB of storage. The following version is supported: @@ -174,6 +180,7 @@ The header files that are required from a Microsoft SDK/DDK are: npapi.h (Windows 2000,XP,2003 builds) netcfgx.h (NSIS Loopback Adapter installer - Windows 2000,XP,2003 builds) netcfgn.h (NSIS Loopback Adapter installer - Windows 2000,XP,2003 builds) + normalization.h (AFS Cache Manager) These files come from the following Microsoft DDKs/SDKs: @@ -184,6 +191,9 @@ These files come from the following Microsoft DDKs/SDKs: Windows XP/2003 DDK - inc/wxp/ + normalization.h: + Microsoft IDN Mitigation APIs 1.1 - include/ + STEP D. Configure NTBUILD.BAT. The NTBUILD.BAT file copied to the OpenAFS base directory must be diff --git a/src/WINNT/afsd/NTMakefile b/src/WINNT/afsd/NTMakefile index 1af81b20ea..5d4c5605a4 100644 --- a/src/WINNT/afsd/NTMakefile +++ b/src/WINNT/afsd/NTMakefile @@ -5,7 +5,7 @@ # License. For details, see the LICENSE file in the top-level source # directory or online at http://www.openafs.org/dl/license10.html -AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL" -I..\kfw\inc\loadfuncs -I..\kfw\inc\krb5 -I..\kfw\inc\leash -I..\afsrdr\common -I..\afsrdr\user -IC:\winddk\IFSKit\inc\wnet +AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) /D"_AFXDLL" /DSMB_UNICODE -I..\kfw\inc\loadfuncs -I..\kfw\inc\krb5 -I..\kfw\inc\leash -I..\afsrdr\common -I..\afsrdr\user -IC:\winddk\IFSKit\inc\wnet AFSDEV_NETGUI = 1 RELDIR=WINNT\afsd diff --git a/src/WINNT/afsd/afsd_init.c b/src/WINNT/afsd/afsd_init.c index 14a3fff11c..a9e3954f13 100644 --- a/src/WINNT/afsd/afsd_init.c +++ b/src/WINNT/afsd/afsd_init.c @@ -995,6 +995,15 @@ int afsd_InitCM(char **reasonP) } #endif /* AFS_FREELANCE_CLIENT */ + dummyLen = sizeof(smb_UseUnicode); + code = RegQueryValueEx(parmKey, "NegotiateUnicode", NULL, NULL, + (BYTE *) &smb_UseUnicode, &dummyLen); + if (code != ERROR_SUCCESS) { + smb_UseUnicode = 1; /* default on */ + } + afsi_log("SMB Server Unicode Support is %s", + smb_UseUnicode ? "enabled" : "disabled"); + dummyLen = sizeof(smb_hideDotFiles); code = RegQueryValueEx(parmKey, "HideDotFiles", NULL, NULL, (BYTE *) &smb_hideDotFiles, &dummyLen); @@ -1243,6 +1252,8 @@ int afsd_InitCM(char **reasonP) cm_InitCallback(); + cm_InitNormalization(); + code = cm_InitMappedMemory(virtualCache, cm_CachePath, stats, volumes, cells, cm_chunkSize, cacheBlocks, blockSize); afsi_log("cm_InitMappedMemory code %x", code); if (code != 0) { @@ -1776,7 +1787,9 @@ LONG __stdcall afsd_ExceptionFilter(EXCEPTION_POINTERS *ep) void afsd_SetUnhandledExceptionFilter() { +#ifndef NOTRACE SetUnhandledExceptionFilter(afsd_ExceptionFilter); +#endif } #ifdef _DEBUG diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index 154c876d2b..9683176e30 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -45,6 +45,9 @@ #define PIOCTL_LOGON 0x1 #define MAX_PATH 260 +static const char utf8_prefix[] = UTF8_PREFIX; +static const int utf8_prefix_size = sizeof(utf8_prefix) - sizeof(char); + osi_mutex_t cm_Afsdsbmt_Lock; extern afs_int32 cryptall; @@ -199,6 +202,7 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, char * relativePath; char * lastComponent = NULL; afs_uint32 follow = (flags & CM_PARSE_FLAG_LITERAL ? CM_FLAG_NOMOUNTCHASE : CM_FLAG_FOLLOW); + int free_path = FALSE; relativePath = ioctlp->inDatap; /* setup the next data value for the caller to use */ @@ -219,11 +223,47 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, * file system API. Therefore, they are not OEM characters but * whatever the display character set is. */ + // TranslateExtendedChars(relativePath); /* This is usually nothing, but for StatMountPoint it is the file name. */ // TranslateExtendedChars(ioctlp->inDatap); + /* If the string starts with our UTF-8 prefix (which is the + sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8 + strings), we assume that the provided path is UTF-8. Otherwise + we have to convert the string to UTF-8, since that is what we + want to use everywhere else.*/ + + if (memcmp(relativePath, utf8_prefix, utf8_prefix_size) == 0) { + int len, normalized_len; + char * normalized_path; + + /* String is UTF-8 */ + relativePath += utf8_prefix_size; + ioctlp->flags |= SMB_IOCTLFLAG_USEUTF8; + + len = (ioctlp->inDatap - relativePath); + + normalized_len = cm_NormalizeUtf8String(relativePath, len, NULL, 0); + + if (normalized_len > len) { + normalized_path = malloc(normalized_len); + free_path = TRUE; + } else { + normalized_path = relativePath; + } + + cm_NormalizeUtf8String(relativePath, len, normalized_path, normalized_len); + + if (normalized_path != relativePath) + relativePath = normalized_path; + } else { + /* Not a UTF-8 string */ + /* TODO: If this is an OEM string, we should convert it to + UTF-8. */ + } + if (relativePath[0] == relativePath[1] && relativePath[1] == '\\' && !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName))) @@ -257,6 +297,8 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, free(sharePath); if (code) { osi_Log1(afsd_logp,"cm_ParseIoctlPath [1] code 0x%x", code); + if (free_path) + free(relativePath); return code; } @@ -279,6 +321,8 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, cm_ReleaseSCache(substRootp); if (code) { osi_Log1(afsd_logp,"cm_ParseIoctlPath [2] code 0x%x", code); + if (free_path) + free(relativePath); return code; } } else { @@ -304,6 +348,8 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, userp, shareName, reqp, &substRootp); if (code) { osi_Log1(afsd_logp,"cm_ParseIoctlPath [3] code 0x%x", code); + if (free_path) + free(relativePath); return code; } @@ -327,6 +373,8 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, if (code) { cm_ReleaseSCache(substRootp); osi_Log1(afsd_logp,"cm_ParseIoctlPath code [4] 0x%x", code); + if (free_path) + free(relativePath); return code; } } @@ -336,6 +384,8 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, userp, ioctlp->tidPathp, reqp, &substRootp); if (code) { osi_Log1(afsd_logp,"cm_ParseIoctlPath [6] code 0x%x", code); + if (free_path) + free(relativePath); return code; } @@ -358,6 +408,8 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, if (code) { cm_ReleaseSCache(substRootp); osi_Log1(afsd_logp,"cm_ParseIoctlPath [7] code 0x%x", code); + if (free_path) + free(relativePath); return code; } } @@ -367,6 +419,9 @@ long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, /* and return success */ osi_Log1(afsd_logp,"cm_ParseIoctlPath [8] code 0x%x", code); + + if (free_path) + free(relativePath); return 0; } @@ -458,8 +513,47 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, char tbuffer[1024]; char *tp, *jp; cm_scache_t *substRootp = NULL; + char *inpathp; + int free_path = FALSE; - StringCbCopyA(tbuffer, sizeof(tbuffer), ioctlp->inDatap); + inpathp = ioctlp->inDatap; + + /* If the string starts with our UTF-8 prefix (which is the + sequence [ESC,'%','G'] as used by ISO-2022 to designate UTF-8 + strings), we assume that the provided path is UTF-8. Otherwise + we have to convert the string to UTF-8, since that is what we + want to use everywhere else.*/ + + if (memcmp(inpathp, utf8_prefix, utf8_prefix_size) == 0) { + int len, normalized_len; + char * normalized_path; + + /* String is UTF-8 */ + inpathp += utf8_prefix_size; + ioctlp->flags |= SMB_IOCTLFLAG_USEUTF8; + + len = strlen(inpathp) + 1; + + normalized_len = cm_NormalizeUtf8String(inpathp, len, NULL, 0); + + if (normalized_len > len) { + normalized_path = malloc(normalized_len); + free_path = TRUE; + } else { + normalized_path = inpathp; + } + + cm_NormalizeUtf8String(inpathp, len, normalized_path, normalized_len); + + if (normalized_path != inpathp) + inpathp = normalized_path; + } else { + /* Not a UTF-8 string */ + /* TODO: If this is an OEM string, we should convert it to + UTF-8. */ + } + + StringCbCopyA(tbuffer, sizeof(tbuffer), inpathp); tp = strrchr(tbuffer, '\\'); jp = strrchr(tbuffer, '/'); if (!tp) @@ -469,7 +563,7 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, if (!tp) { StringCbCopyA(tbuffer, sizeof(tbuffer), "\\"); if (leafp) - StringCbCopyA(leafp, LEAF_SIZE, ioctlp->inDatap); + StringCbCopyA(leafp, LEAF_SIZE, inpathp); } else { *tp = 0; @@ -477,6 +571,10 @@ long cm_ParseIoctlParent(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp, StringCbCopyA(leafp, LEAF_SIZE, tp+1); } + if (free_path) + free(inpathp); + inpathp = NULL; /* We don't need this from this point on */ + if (tbuffer[0] == tbuffer[1] && tbuffer[1] == '\\' && !_strnicmp(cm_NetbiosName,tbuffer+2,strlen(cm_NetbiosName))) @@ -847,6 +945,7 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_cell_t *cellp; cm_req_t req; struct rx_connection * callp; + int len; cm_InitReq(&req); @@ -879,11 +978,17 @@ long cm_IoctlSetVolumeStatus(struct smb_ioctl *ioctlp, struct cm_user *userp) cp = ioctlp->inDatap; memcpy((char *)&volStat, cp, sizeof(AFSFetchVolumeStatus)); cp += sizeof(AFSFetchVolumeStatus); - StringCbCopyA(volName, sizeof(volName), cp); - cp += strlen(volName)+1; - StringCbCopyA(offLineMsg, sizeof(offLineMsg), cp); - cp += strlen(offLineMsg)+1; - StringCbCopyA(motd, sizeof(motd), cp); + + len = strlen(cp) + 1; + cm_NormalizeUtf8String(cp, len, volName, sizeof(volName)); + cp += len; + + len = strlen(cp) + 1; + cm_NormalizeUtf8String(cp, len, offLineMsg, sizeof(offLineMsg)); + cp += len; + + len = strlen(cp) + 1; + cm_NormalizeUtf8String(cp, len, motd, sizeof(motd)); storeStat.Mask = 0; if (volStat.MinQuota != -1) { storeStat.MinQuota = volStat.MinQuota; @@ -1906,7 +2011,9 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp) return code; /* Translate chars for the mount point name */ + if (!(ioctlp->flags & SMB_IOCTLFLAG_USEUTF8)) { TranslateExtendedChars(leaf); + } /* * The fs command allows the user to specify partial cell names on NT. These must @@ -1975,19 +2082,45 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_attr_t tattr; char *cp; cm_req_t req; + char *symlp; + int free_syml = FALSE; cm_InitReq(&req); code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf); if (code) return code; + if (!(ioctlp->flags & SMB_IOCTLFLAG_USEUTF8)) { /* Translate chars for the link name */ TranslateExtendedChars(leaf); /* Translate chars for the linked to name */ TranslateExtendedChars(ioctlp->inDatap); + } - cp = ioctlp->inDatap; /* contents of link */ + symlp = ioctlp->inDatap; /* contents of link */ + + { + char * normalized; + int normalized_len; + + int len = strlen(symlp) + 1; + + normalized_len = cm_NormalizeUtf8String(symlp, len, NULL, 0); + if (normalized_len > len) { + normalized = malloc(normalized_len); + free_syml = TRUE; + } else { + normalized = symlp; + } + + cm_NormalizeUtf8String(symlp, len, normalized, normalized_len); + + if (symlp != normalized) + symlp = normalized; + } + + cp = symlp; #ifdef AFS_FREELANCE_CLIENT if (cm_freelanceEnabled && dscp == cm_data.rootSCachep) { @@ -2023,6 +2156,9 @@ long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp) cm_ReleaseSCache(dscp); + if (free_syml) + free(symlp); + return code; } @@ -2891,11 +3027,43 @@ long cm_IoctlGetSMBName(smb_ioctl_t *ioctlp, cm_user_t *userp) return 0; } +long cm_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user * userp) +{ + long result = 0; +#ifdef SMB_UNICODE + long cmd; + + cm_SkipIoctlPath(ioctlp); + + memcpy(&cmd, ioctlp->inDatap, sizeof(long)); + + if (cmd & 2) { + /* Setting the Unicode flag */ + LONG newflag; + + newflag = ((cmd & 1) == 1); + + InterlockedExchange(&smb_UseUnicode, newflag); + } + + result = smb_UseUnicode; +#else + result = 2; +#endif + + memcpy(ioctlp->outDatap, &result, sizeof(result)); + ioctlp->outDatap += sizeof(result); + + return 0; +} + long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp) { long cmd; afsUUID uuid; + cm_SkipIoctlPath(ioctlp); + memcpy(&cmd, ioctlp->inDatap, sizeof(long)); if (cmd) { /* generate a new UUID */ @@ -2910,6 +3078,8 @@ long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp) return 0; } + + /* * functions to dump contents of various structures. * In debug build (linked with crt debug library) will dump allocated but not freed memory @@ -3119,7 +3289,6 @@ long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp) struct VolStatTest * testp; cm_req_t req; afs_uint32 n; - size_t len; cm_InitReq(&req); diff --git a/src/WINNT/afsd/cm_ioctl.h b/src/WINNT/afsd/cm_ioctl.h index be3715f4af..934959a12f 100644 --- a/src/WINNT/afsd/cm_ioctl.h +++ b/src/WINNT/afsd/cm_ioctl.h @@ -100,6 +100,12 @@ extern char * cm_sysName; extern unsigned int cm_sysNameCount; extern char * cm_sysNameList[MAXNUMSYSNAMES]; +/* Paths that are passed into pioctl calls can be specified using + UTF-8. These strings are prefixed with UTF8_PREFIX defined below. + The sequence ESC '%' 'G' is used by ISO-2022 to designate UTF-8 + strings. */ +#define UTF8_PREFIX "\33%G" + /* flags for rxstats pioctl */ #define AFSCALL_RXSTATS_MASK 0x7 /* Valid flag bits */ @@ -223,6 +229,8 @@ extern long cm_IoctlGetFileType(smb_ioctl_t *ioctlp, cm_user_t *userp); extern long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp); +extern long cm_IoctlUnicodeControl(struct smb_ioctl *ioctlp, struct cm_user * userp); + #endif /* __CM_IOCTL_INTERFACES_ONLY__ */ #endif /* __CM_IOCTL_H_ENV__ */ diff --git a/src/WINNT/afsd/cm_utils.c b/src/WINNT/afsd/cm_utils.c index 8b26f5064a..fc1d8fb544 100644 --- a/src/WINNT/afsd/cm_utils.c +++ b/src/WINNT/afsd/cm_utils.c @@ -69,6 +69,9 @@ #include #include +#define STRSAFE_NO_DEPRECATE +#include + static osi_once_t cm_utilsOnce; @@ -359,3 +362,276 @@ void cm_FreeSpace(cm_space_t *tsp) cm_spaceListp = tsp; lock_ReleaseWrite(&cm_utilsLock); } + +/* This is part of the Microsoft Internationalized Domain Name + Mitigation APIs. */ +#include + +int +(WINAPI *pNormalizeString)( __in NORM_FORM NormForm, + __in_ecount(cwSrcLength) LPCWSTR lpSrcString, + __in int cwSrcLength, + __out_ecount(cwDstLength) LPWSTR lpDstString, + __in int cwDstLength ) = NULL; + +BOOL +(WINAPI *pIsNormalizedString)( __in NORM_FORM NormForm, + __in_ecount(cwLength) LPCWSTR lpString, + __in int cwLength ) = NULL; + + +#define NLSDLLNAME "Normaliz.dll" +#define NLSMAXCCH 1024 +#define NLSERRCCH 8 + +#define AFS_NORM_FORM NormalizationC + +long cm_InitNormalization(void) +{ + HMODULE h_Nls; + + if (pNormalizeString != NULL) + return 0; + + h_Nls = LoadLibrary(NLSDLLNAME); + if (h_Nls == INVALID_HANDLE_VALUE) { + afsi_log("Can't load " NLSDLLNAME ": LastError=%d", GetLastError()); + return 1; + } + + pNormalizeString = GetProcAddress(h_Nls, "NormalizeString"); + pIsNormalizedString = GetProcAddress(h_Nls, "IsNormalizedString"); + + return (pNormalizeString && pIsNormalizedString); +} + +/* \brief Normalize a UTF-16 string. + + If the supplied destination buffer is + insufficient or NULL, then a new buffer will be allocated to hold + the normalized string. + + \param[in] src : Source UTF-16 string. Length is specified in + cch_src. + + \param[in] cch_src : The character count in cch_src is assumed to + be tight and include the terminating NULL character if there is + one. If the NULL is absent, the resulting string will not be + NULL terminated. + + \param[out] ext_dest : The destination buffer. Can be NULL, in + which case *pcch_dest MUST be NULL. + + \param[in,out] pcch_dest : On entry *pcch_dest contains a count of + characters in the destination buffer. On exit, it will contain + a count of characters that were copied to the destination + buffer. + + Returns a pointer to the buffer containing the normalized string or + NULL if the call was unsuccessful. If the returned destination + buffer is different fron the supplied buffer and non-NULL, it + should be freed using free(). +*/ +static wchar_t * +NormalizeUtf16String(const wchar_t * src, int cch_src, wchar_t * ext_dest, int *pcch_dest) +{ + if ((pIsNormalizedString && (*pIsNormalizedString)(AFS_NORM_FORM, src, cch_src)) || + (!pNormalizeString)) { + + int rv; + DWORD gle; + int tries = 10; + wchar_t * dest; + int cch_dest = *pcch_dest; + + dest = ext_dest; + + while (tries-- > 0) { + + rv = (*pNormalizeString)(AFS_NORM_FORM, src, cch_src, dest, cch_dest); + + if (rv <= 0 && (gle = GetLastError()) != ERROR_SUCCESS) { +#ifdef DEBUG + osi_Log1(afsd_logp, "NormalizeUtf16String error = %d", gle); +#endif + if (gle == ERROR_INSUFFICIENT_BUFFER) { + + /* The buffer wasn't big enough. We are going to + try allocating one. */ + + cch_dest = (-rv) + NLSERRCCH; + goto cont; + + } else { + /* Something else is wrong */ + break; + } + + } else if (rv < 0) { /* rv < 0 && gle == ERROR_SUCCESS */ + + /* Technically not one of the expected outcomes */ + break; + + } else { /* rv > 0 || (rv == 0 && gle == ERROR_SUCCESS) */ + + /* Possibly succeeded */ + + if (rv == 0) { /* Succeeded and the return string is empty */ + *pcch_dest = 0; + return dest; + } + + if (cch_dest == 0) { + /* Nope. We only calculated the required size of the buffer */ + + cch_dest = rv + NLSERRCCH; + goto cont; + } + + *pcch_dest = rv; + + /* Success! */ + return dest; + } + + cont: + if (dest != ext_dest && dest) + free(dest); + dest = malloc(cch_dest * sizeof(wchar_t)); + } + + /* Failed */ + + if (dest != ext_dest && dest) + free(dest); + + *pcch_dest = 0; + return NULL; + } else { + + /* No need to or unable to normalize. Just copy the string */ + if (SUCCEEDED(StringCchCopyNW(ext_dest, *pcch_dest, src, cch_src))) { + *pcch_dest = cch_src; + return ext_dest; + } else { + *pcch_dest = 0; + return NULL; + } + } +} + +/* \brief Normalize a UTF-16 string into a UTF-8 string. + + \param[in] src : Source string. + + \param[in] cch_src : Count of characters in src. If the count includes the + NULL terminator, then the resulting string will be NULL + terminated. If it is -1, then src is assumed to be NULL + terminated. + + \param[out] adest : Destination buffer. + + \param[in] cch_adest : Number of characters in the destination buffer. + + Returns the number of characters stored into cch_adest. This will + include the terminating NULL if cch_src included the terminating + NULL or was -1. If this is 0, then the operation was unsuccessful. + */ +long cm_NormalizeUtf16StringToUtf8(const wchar_t * src, int cch_src, + char * adest, int cch_adest) +{ + if (cch_src < 0) { + size_t cch; + + if (FAILED(StringCchLengthW(src, NLSMAXCCH, &cch))) + return CM_ERROR_TOOBIG; + + cch_src = cch+1; + } + + { + wchar_t nbuf[NLSMAXCCH]; + wchar_t * normalized; + int cch_norm = NLSMAXCCH; + + normalized = NormalizeUtf16String(src, cch_src, nbuf, &cch_norm); + if (normalized) { + cch_adest = WideCharToMultiByte(CP_UTF8, 0, normalized, cch_norm, + adest, cch_adest, NULL, 0); + + if (normalized != nbuf && normalized) + free(normalized); + + return cch_adest; + + } else { + + return 0; + + } + } +} + + +/* \brief Normalize a UTF-8 string. + + \param[in] src String to normalize. + + \param[in] cch_src : Count of characters in src. If this value is + -1, then src is assumed to be NULL terminated. The translated + string will be NULL terminated only if this is -1 or the count + includes the terminating NULL. + + \param[out] adest : Destination string. + + \param[in] cch_adest : Number of characters in the destination + string. + + Returns the number of characters stored into adest or 0 if the call + was unsuccessful. + */ +long cm_NormalizeUtf8String(const char * src, int cch_src, + char * adest, int cch_adest) +{ + wchar_t wsrcbuf[NLSMAXCCH]; + wchar_t *wnorm; + int cch; + int cch_norm; + + /* Get some edge cases out first, so we don't have to worry about + cch_src being 0 etc. */ + if (cch_src == 0) { + return 0; + } else if (*src == '\0') { + *adest = '\0'; + return 1; + } + + cch = MultiByteToWideChar(CP_UTF8, 0, src, cch_src * sizeof(char), + wsrcbuf, NLSMAXCCH); + + if (cch == 0) { +#ifdef DEBUG + DebugBreak(); +#endif + return 0; + } + + cch_norm = 0; + wnorm = NormalizeUtf16String(wsrcbuf, cch, NULL, &cch_norm); + if (wnorm == NULL) { +#ifdef DEBUG + DebugBreak(); +#endif + return 0; + } + + cch = WideCharToMultiByte(CP_UTF8, 0, wnorm, cch_norm, + adest, cch_adest * sizeof(char), + NULL, FALSE); + + if (wnorm) + free(wnorm); + + return cch; +} diff --git a/src/WINNT/afsd/cm_utils.h b/src/WINNT/afsd/cm_utils.h index 2f514783ea..06523bf3a6 100644 --- a/src/WINNT/afsd/cm_utils.h +++ b/src/WINNT/afsd/cm_utils.h @@ -28,4 +28,9 @@ extern long cm_MapRPCError(long error, cm_req_t *reqp); extern long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp); extern long cm_MapVLRPCError(long error, cm_req_t *reqp); +extern long cm_InitNormalization(void); +extern long cm_NormalizeUtf16StringToUtf8(const wchar_t * src, int cch_src, + char * adest, int cch_adest); +extern long cm_NormalizeUtf8String(const char * src, int cch_src, + char * adest, int cch_adest); #endif /* __CM_UTILS_H_ENV__ */ diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index 076cc32f94..aa38069e2b 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -251,7 +251,7 @@ InAFS(char *apath) blob.out_size = MAXSIZE; blob.out = space; - code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1); if (code) { if ((errno == EINVAL) || (errno == ENOENT)) return 0; @@ -269,7 +269,7 @@ IsFreelanceRoot(char *apath) blob.out_size = MAXSIZE; blob.out = space; - code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1); if (code == 0) return !stricmp("Freelance.Local.Root",space); return 1; /* assume it is because it is more restrictive that way */ @@ -612,7 +612,6 @@ ParseAcl (char *astr) } ta->minuslist = first; - exit: return ta; nminus_err: @@ -929,7 +928,7 @@ SetACLCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.in_size = idf; blob.in = blob.out = space; - code = pioctl(ti->data, VIOCGETAL, &blob, 1); + code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -992,7 +991,7 @@ SetACLCmd(struct cmd_syndesc *as, void *arock) blob.in = AclToString(ta); blob.out_size=0; blob.in_size = 1+(long)strlen(blob.in); - code = pioctl(ti->data, VIOCSETAL, &blob, 1); + code = pioctl_utf8(ti->data, VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) { if (ta->dfs) { @@ -1069,7 +1068,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.in_size = idf; blob.in = blob.out = space; - code = pioctl(as->parms[0].items->data, VIOCGETAL, &blob, 1); + code = pioctl_utf8(as->parms[0].items->data, VIOCGETAL, &blob, 1); if (code) { Die(errno, as->parms[0].items->data); return 1; @@ -1086,7 +1085,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.in_size = idf; blob.in = blob.out = space; - code = pioctl(ti->data, VIOCGETAL, &blob, 1); + code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -1130,7 +1129,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock) blob.in = AclToString(ta); blob.out_size=0; blob.in_size = 1+(long)strlen(blob.in); - code = pioctl(ti->data, VIOCSETAL, &blob, 1); + code = pioctl_utf8(ti->data, VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) { fprintf(stderr, @@ -1148,7 +1147,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock) return error; } -/* pioctl() call to get the cellname of a pathname */ +/* pioctl_utf8() call to get the cellname of a pathname */ static afs_int32 GetCell(char *fname, char *cellname) { @@ -1159,7 +1158,7 @@ GetCell(char *fname, char *cellname) blob.out_size = MAXCELLCHARS; blob.out = cellname; - code = pioctl(fname, VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_utf8(fname, VIOC_FILE_CELL_NAME, &blob, 1); return code; } @@ -1258,7 +1257,7 @@ CleanACLCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.in_size = 0; blob.out = space; - code = pioctl(ti->data, VIOCGETAL, &blob, 1); + code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -1289,7 +1288,7 @@ CleanACLCmd(struct cmd_syndesc *as, void *arock) blob.in=AclToString(ta); blob.in_size = (long)strlen(blob.in)+1; blob.out_size = 0; - code = pioctl(ti->data, VIOCSETAL, &blob, 1); + code = pioctl_utf8(ti->data, VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) { fprintf(stderr, @@ -1352,7 +1351,7 @@ ListACLCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.in_size = idf; blob.in = blob.out = space; - code = pioctl(ti->data, VIOCGETAL, &blob, 1); + code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -1415,7 +1414,7 @@ FlushAllCmd(struct cmd_syndesc *as, void *arock) struct ViceIoctl blob; blob.in_size = blob.out_size = 0; - code = pioctl(NULL, VIOC_FLUSHALL, &blob, 0); + code = pioctl_utf8(NULL, VIOC_FLUSHALL, &blob, 0); if (code) { fprintf(stderr, "Error flushing all "); return 1; @@ -1434,7 +1433,7 @@ FlushVolumeCmd(struct cmd_syndesc *as, void *arock) SetDotDefault(&as->parms[0].items); for(ti=as->parms[0].items; ti; ti=ti->next) { blob.in_size = blob.out_size = 0; - code = pioctl(ti->data, VIOC_FLUSHVOLUME, &blob, 0); + code = pioctl_utf8(ti->data, VIOC_FLUSHVOLUME, &blob, 0); if (code) { fprintf(stderr, "Error flushing volume "); perror(ti->data); @@ -1468,7 +1467,7 @@ FlushCmd(struct cmd_syndesc *as, void *arock) blob.in = &options; blob.out_size = 0; - code = pioctl(ti->data, VIOCFLUSH, &blob, 0); + code = pioctl_utf8(ti->data, VIOCFLUSH, &blob, 0); if (code) { if (errno == EMFILE) { fprintf(stderr, "%s: Can't flush active file %s\n", pn, @@ -1550,7 +1549,7 @@ SetVolCmd(struct cmd_syndesc *as, void *arock) { input += strlen(motd) + 1; } else *(input++) = '\0'; - code = pioctl(ti->data,VIOCSETVOLSTAT, &blob, 1); + code = pioctl_utf8(ti->data,VIOCSETVOLSTAT, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -1619,7 +1618,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock) blob.out_size = sizeof(cm_fid_t); blob.out = (char *) &fid; - if (0 == pioctl(ti->data, VIOCGETFID, &blob, 1)) { + if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1)) { options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID; options.fid = fid; } else { @@ -1631,12 +1630,12 @@ ExamineCmd(struct cmd_syndesc *as, void *arock) blob.out_size = sizeof(filetype); blob.out = &filetype; - code = pioctl(ti->data, VIOC_GETFILETYPE, &blob, 1); + code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1); blob.out_size = MAXCELLCHARS; blob.out = cell; - code = pioctl(ti->data, VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1); printf("%s %s (%u.%u.%u) contained in cell %s\n", filetypestr(filetype), ti->data, fid.volume, fid.vnode, fid.unique, @@ -1644,7 +1643,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock) blob.out_size = 2 * sizeof(afs_uint32); blob.out = (char *) &owner; - if (0 == pioctl(ti->data, VIOCGETOWNER, &blob, 1)) { + if (0 == pioctl_utf8(ti->data, VIOCGETOWNER, &blob, 1)) { char oname[PR_MAXNAMELEN] = "(unknown)"; char confDir[257]; @@ -1658,7 +1657,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock) blob.out = space; blob.out_size = MAXSIZE; - code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1); + code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1); if (code == 0) { status = (VolumeStatus *)space; name = (char *)status + sizeof(*status); @@ -1671,7 +1670,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock) } errno = 0; - code = pioctl(ti->data, VIOC_PATH_AVAILABILITY, &blob, 1); + code = pioctl_utf8(ti->data, VIOC_PATH_AVAILABILITY, &blob, 1); switch (errno) { case 0: printf("Volume is online\n"); @@ -1713,7 +1712,7 @@ ListQuotaCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.in_size = 0; blob.out = space; - code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1); + code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -1759,7 +1758,7 @@ WhereIsCmd(struct cmd_syndesc *as, void *arock) blob.out_size = sizeof(cm_fid_t); blob.out = (char *) &fid; - if (0 == pioctl(ti->data, VIOCGETFID, &blob, 1)) { + if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1)) { options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID; options.fid = fid; } else { @@ -1771,12 +1770,12 @@ WhereIsCmd(struct cmd_syndesc *as, void *arock) blob.out_size = sizeof(filetype); blob.out = &filetype; - code = pioctl(ti->data, VIOC_GETFILETYPE, &blob, 1); + code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1); blob.out_size = MAXSIZE; blob.out = space; memset(space, 0, sizeof(space)); - code = pioctl(ti->data, VIOCWHEREIS, &blob, 1); + code = pioctl_utf8(ti->data, VIOCWHEREIS, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -1817,7 +1816,7 @@ DiskFreeCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.in_size = 0; blob.out = space; - code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1); + code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -1846,7 +1845,7 @@ QuotaCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.in_size = 0; blob.out = space; - code = pioctl(ti->data, VIOCGETVOLSTAT, &blob, 1); + code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -1994,7 +1993,7 @@ ListMountCmd(struct cmd_syndesc *as, void *arock) blob.out = space; memset(space, 0, MAXSIZE); - code = pioctl(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1); + code = pioctl_utf8(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1); if (code == 0) { printf("'%s' is a %smount point for volume '%s'\n", @@ -2091,7 +2090,7 @@ MakeMountCmd(struct cmd_syndesc *as, void *arock) blob.in_size = 0; blob.out_size = sizeof(localCellName); blob.out = localCellName; - code = pioctl(parent, VIOC_GET_WS_CELL, &blob, 1); + code = pioctl_utf8(parent, VIOC_GET_WS_CELL, &blob, 1); if (!code) cellName = localCellName; } @@ -2142,7 +2141,7 @@ MakeMountCmd(struct cmd_syndesc *as, void *arock) blob.in_size = 1 + (long)strlen(space); blob.in = space; blob.out = NULL; - code = pioctl(path, VIOC_AFS_CREATE_MT_PT, &blob, 0); + code = pioctl_utf8(path, VIOC_AFS_CREATE_MT_PT, &blob, 0); #else /* not WIN32 */ code = symlink(space, path); #endif /* not WIN32 */ @@ -2203,7 +2202,7 @@ RemoveMountCmd(struct cmd_syndesc *as, void *arock) { blob.in_size = (long)strlen(tp)+1; blob.out = lsbuffer; blob.out_size = sizeof(lsbuffer); - code = pioctl(tbuffer, VIOC_AFS_STAT_MT_PT, &blob, 0); + code = pioctl_utf8(tbuffer, VIOC_AFS_STAT_MT_PT, &blob, 0); if (code) { if (errno == EINVAL) { fprintf(stderr,"%s: '%s' is not a mount point.\n", pn, ti->data); @@ -2223,7 +2222,7 @@ RemoveMountCmd(struct cmd_syndesc *as, void *arock) { blob.out_size = 0; blob.in = tp; blob.in_size = (long)strlen(tp)+1; - code = pioctl(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0); + code = pioctl_utf8(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0); if (code) { Die(errno, ti->data); error = 1; @@ -2306,7 +2305,7 @@ CheckServersCmd(struct cmd_syndesc *as, void *arock) #endif /* WIN32 */ } - code = pioctl(0, VIOCCKSERV, &blob, 1); + code = pioctl_utf8(0, VIOCCKSERV, &blob, 1); if (code) { if ((errno == EACCES) && (checkserv.tinterval > 0)) { printf("Must be root to change -interval\n"); @@ -2376,7 +2375,7 @@ MessagesCmd(struct cmd_syndesc *as, void *arock) if (code) return 1; - code = pioctl(0, VIOC_GAG, &blob, 1); + code = pioctl_utf8(0, VIOC_GAG, &blob, 1); if (code) { Die(errno, 0); return 1; @@ -2392,7 +2391,7 @@ CheckVolumesCmd(struct cmd_syndesc *as, void *arock) blob.in_size = 0; blob.out_size = 0; - code = pioctl(0, VIOCCKBACK, &blob, 1); + code = pioctl_utf8(0, VIOCCKBACK, &blob, 1); if (code) { Die(errno, 0); return 1; @@ -2436,7 +2435,7 @@ SetCacheSizeCmd(struct cmd_syndesc *as, void *arock) blob.in = (char *) &temp; blob.in_size = sizeof(afs_int32); blob.out_size = 0; - code = pioctl(0, VIOCSETCACHESIZE, &blob, 1); + code = pioctl_utf8(0, VIOCSETCACHESIZE, &blob, 1); if (code) { Die(errno, (char *) 0); return 1; @@ -2458,7 +2457,7 @@ GetCacheParmsCmd(struct cmd_syndesc *as, void *arock) blob.in_size = 0; blob.out_size = sizeof(parms); blob.out = (char *) &parms; - code = pioctl(0, VIOCGETCACHEPARMS, &blob, 1); + code = pioctl_utf8(0, VIOCGETCACHEPARMS, &blob, 1); if (code) { Die(errno, NULL); return 1; @@ -2494,7 +2493,7 @@ ListCellsCmd(struct cmd_syndesc *as, void *arock) blob.in_size = sizeof(afs_int32); blob.in = space; blob.out = space; - code = pioctl(0, VIOCGETCELL, &blob, 1); + code = pioctl_utf8(0, VIOCGETCELL, &blob, 1); if (code < 0) { if (errno == EDOM) break; /* done with the list */ @@ -2545,7 +2544,7 @@ ListAliasesCmd(struct cmd_syndesc *as, void *arock) blob.in_size = sizeof(afs_int32); blob.in = space; blob.out = space; - code = pioctl(0, VIOC_GETALIAS, &blob, 1); + code = pioctl_utf8(0, VIOC_GETALIAS, &blob, 1); if (code < 0) { if (errno == EDOM) break; /* done with the list */ @@ -2592,7 +2591,7 @@ CallBackRxConnCmd(struct cmd_syndesc *as, void *arock) blob.in = (char *) &hostAddr; blob.out = (char *) &hostAddr; - code = pioctl(0, VIOC_CBADDR, &blob, 1); + code = pioctl_utf8(0, VIOC_CBADDR, &blob, 1); if (code < 0) { Die(errno, 0); return 1; @@ -2667,7 +2666,7 @@ NewCellCmd(struct cmd_syndesc *as, void *arock) blob.in_size = size; blob.in = space; blob.out_size = 0; - code = pioctl(0, VIOCNEWCELL, &blob, 1); + code = pioctl_utf8(0, VIOCNEWCELL, &blob, 1); if (code < 0) Die(errno, 0); return 0; @@ -2685,7 +2684,7 @@ NewCellCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.out = space; - code = pioctl((char *) 0, VIOCNEWCELL, &blob, 1); + code = pioctl_utf8((char *) 0, VIOCNEWCELL, &blob, 1); if (code) { Die(errno, (char *) 0); @@ -2719,7 +2718,7 @@ NewAliasCmd(struct cmd_syndesc *as, void *arock) blob.in = space; blob.out_size = 0; blob.out = space; - code = pioctl(0, VIOC_NEWALIAS, &blob, 1); + code = pioctl_utf8(0, VIOC_NEWALIAS, &blob, 1); if (code < 0) { if (errno == EEXIST) { fprintf(stderr, @@ -2765,7 +2764,7 @@ WhichCellCmd(struct cmd_syndesc *as, void *arock) blob.out_size = sizeof(cm_fid_t); blob.out = (char *) &fid; - if (0 == pioctl(ti->data, VIOCGETFID, &blob, 1)) { + if (0 == pioctl_utf8(ti->data, VIOCGETFID, &blob, 1)) { options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID; options.fid = fid; } else { @@ -2777,12 +2776,12 @@ WhichCellCmd(struct cmd_syndesc *as, void *arock) blob.out_size = sizeof(filetype); blob.out = &filetype; - code = pioctl(ti->data, VIOC_GETFILETYPE, &blob, 1); + code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1); blob.out_size = MAXCELLCHARS; blob.out = cell; - code = pioctl(ti->data, VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1); if (code) { if (errno == ENOENT) fprintf(stderr,"%s: no such cell as '%s'\n", pn, ti->data); @@ -2809,7 +2808,7 @@ WSCellCmd(struct cmd_syndesc *as, void *arock) blob.out_size = MAXSIZE; blob.out = space; - code = pioctl(NULL, VIOC_GET_WS_CELL, &blob, 1); + code = pioctl_utf8(NULL, VIOC_GET_WS_CELL, &blob, 1); if (code) { Die(errno, NULL); @@ -2871,7 +2870,7 @@ MonitorCmd(struct cmd_syndesc *as, void *arock) blob.out_size = sizeof(afs_int32); blob.in = (char *) &hostAddr; blob.out = (char *) &hostAddr; - code = pioctl(0, VIOC_AFS_MARINER_HOST, &blob, 1); + code = pioctl_utf8(0, VIOC_AFS_MARINER_HOST, &blob, 1); if (code) { Die(errno, 0); return 1; @@ -2934,7 +2933,7 @@ SysNameCmd(struct cmd_syndesc *as, void *arock) *(input++) = '\0'; } memcpy(space, &setp, sizeof(afs_int32)); - code = pioctl(0, VIOC_AFS_SYSNAME, &blob, 1); + code = pioctl_utf8(0, VIOC_AFS_SYSNAME, &blob, 1); if (code) { Die(errno, 0); return 1; @@ -3040,7 +3039,7 @@ static int ExportAfsCmd(struct cmd_syndesc *as, void *arock) blob.in_size = sizeof(afs_int32); blob.out = (char *) &exportcall; blob.out_size = sizeof(afs_int32); - code = pioctl(0, VIOC_EXPORTAFS, &blob, 1); + code = pioctl_utf8(0, VIOC_EXPORTAFS, &blob, 1); if (code) { if (errno == ENODEV) { fprintf(stderr, @@ -3090,7 +3089,7 @@ GetCellCmd(struct cmd_syndesc *as, void *arock) } blob.in_size = 1+(long)strlen(info.name); blob.in = info.name; - code = pioctl(0, VIOC_GETCELLSTATUS, &blob, 1); + code = pioctl_utf8(0, VIOC_GETCELLSTATUS, &blob, 1); if (code) { if (errno == ENOENT) fprintf(stderr,"%s: the cell named '%s' does not exist\n", pn, info.name); @@ -3166,7 +3165,7 @@ static int SetCellCmd(struct cmd_syndesc *as, void *arock) blob.in = (caddr_t) &args; blob.out_size = 0; blob.out = (caddr_t) 0; - code = pioctl(0, VIOC_SETCELLSTATUS, &blob, 1); + code = pioctl_utf8(0, VIOC_SETCELLSTATUS, &blob, 1); if (code) { Die(errno, info.name); /* XXX added cell name to Die() call */ error = 1; @@ -3218,7 +3217,7 @@ pokeServers(void) { int code; cm_SSetPref_t *ssp; - code = pioctl(0, VIOC_SETSPREFS, &gblob, 1); + code = pioctl_utf8(0, VIOC_SETSPREFS, &gblob, 1); ssp = (cm_SSetPref_t *)space; gblob.in_size = (long)(((char *)&(ssp->servers[0])) - (char *)ssp); @@ -3236,14 +3235,14 @@ pokeServers(void) { int code; - code = pioctl(0, VIOC_SETSPREFS, &gblob, 1); + code = pioctl_utf8(0, VIOC_SETSPREFS, &gblob, 1); if (code && (errno == EINVAL)) { struct setspref *ssp; ssp = (struct setspref *)gblob.in; if (!(ssp->flags & DBservers)) { gblob.in = (void *)&(ssp->servers[0]); gblob.in_size -= ((char *)&(ssp->servers[0])) - (char *)ssp; - code = pioctl(0, VIOC_SETSPREFS33, &gblob, 1); + code = pioctl_utf8(0, VIOC_SETSPREFS33, &gblob, 1); return code ? errno : 0; } fprintf(stderr, @@ -3617,7 +3616,7 @@ GetPrefCmd(struct cmd_syndesc *as, void *arock) in->num_servers = (MAXSIZE - 2*sizeof(short))/sizeof(struct cm_SPref); in->flags = vlservers; - code = pioctl(0, VIOC_GETSPREFS, &blob, 1); + code = pioctl_utf8(0, VIOC_GETSPREFS, &blob, 1); if (code){ perror("getserverprefs pioctl"); Die (errno,0); @@ -3689,7 +3688,7 @@ GetPrefCmd(struct cmd_syndesc *as, void *arock) (MAXSIZE - 2 * sizeof(short)) / sizeof(struct spref); in->flags = vlservers; - code = pioctl(0, VIOC_GETSPREFS, &blob, 1); + code = pioctl_utf8(0, VIOC_GETSPREFS, &blob, 1); if (code) { perror("getserverprefs pioctl"); return 1; @@ -3716,6 +3715,52 @@ GetPrefCmd(struct cmd_syndesc *as, void *arock) } #endif /* WIN32 */ +static afs_int32 +SmbUnicodeCmd(struct cmd_syndesc * asp, void * arock) +{ + long inValue = 0; + long outValue = 0; + long code; + + struct ViceIoctl blob; + + if (asp->parms[0].items) { + /* On */ + + inValue = 3; + } else if (asp->parms[1].items) { + /* Off */ + + inValue = 2; + } + + if (inValue != 0 && !IsAdmin()) { + fprintf (stderr, "Permission denied: Requires AFS Client Administrator access.\n"); + return EACCES; + } + + blob.in_size = sizeof(inValue); + blob.in = (char *) &inValue; + blob.out_size = sizeof(outValue); + blob.out = (char *) &outValue; + + code = pioctl_utf8(NULL, VIOC_UNICODECTL, &blob, 1); + if (code) { + Die(errno, NULL); + return code; + } + + if (outValue != 2) { + printf("Unicode support is %s%s.\n", + ((outValue != 0)? "enabled":"disabled"), + ((inValue != 0)? " for new SMB connections":"")); + } else { + printf("Unicode support is absent in this installation of OpenAFS.\n"); + } + + return 0; +} + static int UuidCmd(struct cmd_syndesc *asp, void *arock) { @@ -3747,7 +3792,7 @@ UuidCmd(struct cmd_syndesc *asp, void *arock) blob.out_size = sizeof(outValue); blob.out = (char *) &outValue; - code = pioctl(NULL, VIOC_UUIDCTL, &blob, 1); + code = pioctl_utf8(NULL, VIOC_UUIDCTL, &blob, 1); if (code) { Die(errno, NULL); return code; @@ -3806,7 +3851,7 @@ TraceCmd(struct cmd_syndesc *asp, void *arock) blob.out_size = sizeof(long); blob.out = (char *) &outValue; - code = pioctl(NULL, VIOC_TRACECTL, &blob, 1); + code = pioctl_utf8(NULL, VIOC_TRACECTL, &blob, 1); if (code) { Die(errno, NULL); return code; @@ -3887,14 +3932,14 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock) /* once per -file */ for (ti = as->parms[1].items; ti; ti = ti->next) { /* Do this solely to see if the file is there */ - code = pioctl(ti->data, VIOCWHEREIS, &blob, 1); + code = pioctl_utf8(ti->data, VIOCWHEREIS, &blob, 1); if (code) { Die(errno, ti->data); error = 1; continue; } - code = pioctl(ti->data, VIOC_STOREBEHIND, &blob, 1); + code = pioctl_utf8(ti->data, VIOC_STOREBEHIND, &blob, 1); if (code) { Die(errno, ti->data); error = 1; @@ -3918,7 +3963,7 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock) */ if (!as->parms[1].items || (allfiles != -1)) { tsb.sb_default = allfiles; - code = pioctl(0, VIOC_STOREBEHIND, &blob, 1); + code = pioctl_utf8(0, VIOC_STOREBEHIND, &blob, 1); if (code) { Die(errno, ((allfiles == -1) ? 0 : "-allfiles")); error = 1; @@ -3961,7 +4006,7 @@ SetCryptCmd(struct cmd_syndesc *as, void *arock) blob.in = (char *) &flag; blob.in_size = sizeof(flag); blob.out_size = 0; - code = pioctl(0, VIOC_SETRXKCRYPT, &blob, 1); + code = pioctl_utf8(0, VIOC_SETRXKCRYPT, &blob, 1); if (code) Die(code, NULL); return 0; @@ -3979,7 +4024,7 @@ GetCryptCmd(struct cmd_syndesc *as, void *arock) blob.out_size = sizeof(flag); blob.out = space; - code = pioctl(0, VIOC_GETRXKCRYPT, &blob, 1); + code = pioctl_utf8(0, VIOC_GETRXKCRYPT, &blob, 1); if (code) Die(code, NULL); @@ -4025,7 +4070,7 @@ MemDumpCmd(struct cmd_syndesc *asp, void *arock) blob.out_size = sizeof(long); blob.out = (char *) &outValue; - code = pioctl(NULL, VIOC_TRACEMEMDUMP, &blob, 1); + code = pioctl_utf8(NULL, VIOC_TRACEMEMDUMP, &blob, 1); if (code) { Die(errno, NULL); return code; @@ -4217,7 +4262,7 @@ GetClientAddrsCmd(struct cmd_syndesc *as, void *arock) in->num_servers = (MAXSIZE - 2 * sizeof(short)) / sizeof(struct spref); /* returns addr in network byte order */ - code = pioctl(0, VIOC_GETCPREFS, &blob, 1); + code = pioctl_utf8(0, VIOC_GETCPREFS, &blob, 1); if (code) { perror("getClientInterfaceAddr pioctl"); return 1; @@ -4306,7 +4351,7 @@ SetClientAddrsCmd(struct cmd_syndesc *as, void *arock) } blob.in_size = sizeUsed - sizeof(struct spref); - code = pioctl(0, VIOC_SETCPREFS, &blob, 1); /* network order */ + code = pioctl_utf8(0, VIOC_SETCPREFS, &blob, 1); /* network order */ if (code) { Die(errno, 0); error = 1; @@ -4417,7 +4462,7 @@ FlushMountCmd(struct cmd_syndesc *as, void *arock) blob.out_size = 0; memset(space, 0, MAXSIZE); - code = pioctl(parent_dir, VIOC_AFS_FLUSHMOUNT, &blob, 1); + code = pioctl_utf8(parent_dir, VIOC_AFS_FLUSHMOUNT, &blob, 1); if (code != 0) { if (errno == EINVAL) { @@ -4457,7 +4502,7 @@ RxStatProcCmd(struct cmd_syndesc *as, void *arock) blob.in_size = sizeof(afs_int32); blob.out_size = 0; - code = pioctl(NULL, VIOC_RXSTAT_PROC, &blob, 1); + code = pioctl_utf8(NULL, VIOC_RXSTAT_PROC, &blob, 1); if (code != 0) { Die(errno, NULL); return 1; @@ -4491,7 +4536,7 @@ RxStatPeerCmd(struct cmd_syndesc *as, void *arock) blob.in_size = sizeof(afs_int32); blob.out_size = 0; - code = pioctl(NULL, VIOC_RXSTAT_PEER, &blob, 1); + code = pioctl_utf8(NULL, VIOC_RXSTAT_PEER, &blob, 1); if (code != 0) { Die(errno, NULL); return 1; @@ -4571,7 +4616,7 @@ TestVolStatCmd(struct cmd_syndesc *as, void *arock) blob.in_size = sizeof(test); blob.out_size = 0; - code = pioctl(NULL, VIOC_VOLSTAT_TEST, &blob, 1); + code = pioctl_utf8(NULL, VIOC_VOLSTAT_TEST, &blob, 1); if (code != 0) { Die(errno, NULL); return 1; @@ -4584,10 +4629,55 @@ TestVolStatCmd(struct cmd_syndesc *as, void *arock) #include "AFS_component_version_number.c" #endif -main(int argc, char **argv) +static void +FreeUtf8CmdLine(int argc, char ** argv) +{ + int i; + for (i=0; i < argc; i++) { + if (argv[i]) + free(argv[i]); + } + free(argv); +} + +static char ** +MakeUtf8Cmdline(int argc, const wchar_t **wargv) +{ + char ** argv; + int i; + + argv = calloc(argc, sizeof(argv[0])); + if (argv == NULL) + return NULL; + + for (i=0; i < argc; i++) { + int s; + + s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, FALSE); + if (s == 0 || + (argv[i] = calloc(s+1, sizeof(char))) == NULL) { + break; + } + + s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], s+1, NULL, FALSE); + if (s == 0) { + break; + } + } + + if (i < argc) { + FreeUtf8CmdLine(argc, argv); + return NULL; + } + + return argv; +} + +int wmain(int argc, wchar_t **wargv) { afs_int32 code; struct cmd_syndesc *ts; + char ** argv; #ifdef AFS_AIX32_ENV /* @@ -4609,6 +4699,8 @@ main(int argc, char **argv) WSAStartup(0x0101, &WSAjunk); #endif /* WIN32 */ + argv = MakeUtf8Cmdline(argc, wargv); + /* try to find volume location information */ osi_Init(); @@ -4885,11 +4977,17 @@ main(int argc, char **argv) cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_OPTIONAL, "volume name or number"); cmd_AddParm(ts, "-state", CMD_SINGLE, CMD_OPTIONAL, "new volume state: online, busy, offline, down"); + ts = cmd_CreateSyntax("smbunicode", SmbUnicodeCmd, NULL, "enable or disable Unicode on new SMB connections"); + cmd_AddParm(ts, "-on", CMD_FLAG, CMD_OPTIONAL, "enable Unicode on new connections"); + cmd_AddParm(ts, "-off", CMD_FLAG, CMD_OPTIONAL, "disable Unicode on new connections"); + code = cmd_Dispatch(argc, argv); if (rxInitDone) rx_Finalize(); + FreeUtf8CmdLine(argc, argv); + return code; } diff --git a/src/WINNT/afsd/fs_utils.c b/src/WINNT/afsd/fs_utils.c index 884fc8e0e6..84c990a7f6 100644 --- a/src/WINNT/afsd/fs_utils.c +++ b/src/WINNT/afsd/fs_utils.c @@ -74,8 +74,7 @@ long fs_GetFullPath(char *pathp, char *outPathp, long outSize) /* there's a drive letter there */ firstp = pathp+2; pathHasDrive = 1; - } - else { + } else { firstp = pathp; pathHasDrive = 0; } @@ -86,7 +85,7 @@ long fs_GetFullPath(char *pathp, char *outPathp, long outSize) return 0; } - GetCurrentDirectory(sizeof(origPath), origPath); + GetCurrentDirectoryA(sizeof(origPath), origPath); doSwitch = 0; if (pathHasDrive && (*pathp & ~0x20) != (origPath[0] & ~0x20)) { @@ -98,14 +97,14 @@ long fs_GetFullPath(char *pathp, char *outPathp, long outSize) newPath[0] = *pathp; newPath[1] = ':'; newPath[2] = 0; - if (!SetCurrentDirectory(newPath)) { + if (!SetCurrentDirectoryA(newPath)) { code = GetLastError(); return code; } } /* now get the absolute path to the current wdir in this drive */ - GetCurrentDirectory(sizeof(tpath), tpath); + GetCurrentDirectoryA(sizeof(tpath), tpath); strcpy(outPathp, tpath+2); /* skip drive letter */ /* if there is a non-null name after the drive, append it */ if (*firstp != 0) { @@ -115,7 +114,7 @@ long fs_GetFullPath(char *pathp, char *outPathp, long outSize) /* finally, if necessary, switch back to our home drive letter */ if (doSwitch) { - SetCurrentDirectory(origPath); + SetCurrentDirectoryA(origPath); } return 0; @@ -197,9 +196,9 @@ void fs_utils_InitMountRoot() char *pmount=mountRoot; DWORD len=sizeof(mountRoot)-1; printf("int mountroot \n"); - if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, + if ((RegOpenKeyExA(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey)!= ERROR_SUCCESS) - || (RegQueryValueEx(parmKey, "Mountroot", NULL, NULL,(LPBYTE)(mountRoot), &len)!= ERROR_SUCCESS) + || (RegQueryValueExA(parmKey, "Mountroot", NULL, NULL,(LPBYTE)(mountRoot), &len)!= ERROR_SUCCESS) || (len==sizeof(mountRoot)-1) ) strcpy(mountRoot, "\\afs"); diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 94ef2581a4..5b133171a0 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -31,6 +31,9 @@ #include "smb.h" #include "lanahelper.h" +#define STRSAFE_NO_DEPRECATE +#include + /* These characters are illegal in Windows filenames */ static char *illegalChars = "\\/:*?\"<>|"; @@ -133,6 +136,9 @@ smb_dirSearch_t *smb_lastDirSearchp; /* hide dot files? */ int smb_hideDotFiles; +/* Negotiate Unicode support? */ +LONG smb_UseUnicode; + /* global state about V3 protocols */ int smb_useV3; /* try to negotiate V3 */ @@ -2065,7 +2071,7 @@ static smb_packet_t *GetPacket(void) smb_packetFreeListp = tbp->nextp; lock_ReleaseWrite(&smb_globalLock); if (!tbp) { - tbp = calloc(65540,1); + tbp = calloc(sizeof(*tbp),1); tbp->magic = SMB_PACKETMAGIC; tbp->ncbp = NULL; tbp->vcp = NULL; @@ -2078,7 +2084,7 @@ static smb_packet_t *GetPacket(void) tbp->ncb_length = 0; tbp->flags = 0; tbp->spacep = NULL; - + tbp->stringsp = NULL; } osi_assertx(tbp->magic == SMB_PACKETMAGIC, "invalid smb_packet_t magic"); @@ -2091,6 +2097,7 @@ smb_packet_t *smb_CopyPacket(smb_packet_t *pkt) tbp = GetPacket(); memcpy(tbp, pkt, sizeof(smb_packet_t)); tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data); + tbp->stringsp = NULL; if (tbp->vcp) smb_HoldVC(tbp->vcp); return tbp; @@ -2118,6 +2125,18 @@ static NCB *GetNCB(void) return ncbp; } +static void FreeSMBStrings(smb_packet_t * pkt) +{ + cm_space_t * s; + cm_space_t * ns; + + for (s = pkt->stringsp; s; s = ns) { + ns = s->nextp; + cm_FreeSpace(s); + } + pkt->stringsp = NULL; +} + void smb_FreePacket(smb_packet_t *tbp) { smb_vc_t * vcp = NULL; @@ -2138,6 +2157,7 @@ void smb_FreePacket(smb_packet_t *tbp) tbp->oddByte = 0; tbp->ncb_length = 0; tbp->flags = 0; + FreeSMBStrings(tbp); lock_ReleaseWrite(&smb_globalLock); if (vcp) @@ -2345,6 +2365,8 @@ void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmValue) *parmDatap++ = parmValue & 0xff; } + + void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp) { char *lastSlashp; @@ -2365,14 +2387,286 @@ void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp } } -unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp) +unsigned char *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp, + char **chainpp, int flags) { + size_t cb; + if (*inp++ != 0x4) return NULL; - if (chainpp) { - *chainpp = inp + strlen(inp) + 1; /* skip over null-terminated string */ + +#ifdef SMB_UNICODE + if (!WANTS_UNICODE(pktp)) + flags |= SMB_STRF_FORCEASCII; +#endif + + cb = sizeof(pktp->data) - (inp - pktp->data); + if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) { +#ifdef DEBUG_UNICODE + DebugBreak(); +#endif + cb = sizeof(pktp->data); } + return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags); +} + +unsigned char *smb_ParseString(smb_packet_t * pktp, unsigned char * inp, + char ** chainpp, int flags) +{ + size_t cb; + +#ifdef SMB_UNICODE + if (!WANTS_UNICODE(pktp)) + flags |= SMB_STRF_FORCEASCII; +#endif + + cb = sizeof(pktp->data) - (inp - pktp->data); + if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) { +#ifdef DEBUG_UNICODE + DebugBreak(); +#endif + cb = sizeof(pktp->data); + } + return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags); +} + +unsigned char *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp, + size_t cb, char ** chainpp, int flags) +{ +#ifdef SMB_UNICODE + if (!WANTS_UNICODE(pktp)) + flags |= SMB_STRF_FORCEASCII; +#endif + + return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags); +} + +unsigned char *smb_ParseStringCch(smb_packet_t * pktp, unsigned char * inp, + size_t cch, char ** chainpp, int flags) +{ + size_t cb = cch; + +#ifdef SMB_UNICODE + if (!WANTS_UNICODE(pktp)) + flags |= SMB_STRF_FORCEASCII; + else + cb = cch * sizeof(wchar_t); +#endif + + return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags); +} + +unsigned char *smb_ParseStringBuf(const unsigned char * bufbase, + cm_space_t ** stringspp, + unsigned char *inp, size_t *pcb_max, + char **chainpp, int flags) +{ +#ifdef SMB_UNICODE + if (!(flags & SMB_STRF_FORCEASCII)) { + size_t cch_src; + int cb_dest; + cm_space_t * spacep; + int null_terms = 0; + + if (bufbase && ((inp - bufbase) % 2) != 0) { + inp++; /* unicode strings are always word aligned */ + } + + if (*pcb_max > 0) { + if (FAILED(StringCchLengthW((const wchar_t *) inp, *pcb_max / sizeof(wchar_t), + &cch_src))) { + cch_src = *pcb_max / sizeof(wchar_t); + *pcb_max = 0; + null_terms = 0; + } else { + *pcb_max -= (cch_src + 1) * sizeof(wchar_t); + null_terms = 1; + } + } else { + return NULL; + } + + spacep = cm_GetSpace(); + spacep->nextp = *stringspp; + *stringspp = spacep; + + if (cch_src == 0) { + if (chainpp) { + *chainpp = inp + sizeof(wchar_t); + } + + spacep->data[0] = '\0'; + return spacep->data; + } + + cb_dest = cm_NormalizeUtf16StringToUtf8((const wchar_t *) inp, cch_src, + spacep->data, sizeof(spacep->data)); + if (cb_dest == 0) { + *stringspp = spacep->nextp; + cm_FreeSpace(spacep); +#ifdef DEBUG_UNICODE + DebugBreak(); +#endif + return NULL; + } + + if (chainpp) + *chainpp = inp + (cch_src + null_terms)*sizeof(wchar_t); + + if (cb_dest == 0) { +#ifdef DEBUG_UNICODE + DebugBreak(); +#endif + } else if (spacep->data[cb_dest - 1] != 0) { + spacep->data[cb_dest++] = 0; + } + + return spacep->data; + + } else { +#endif + /* Not using Unicode */ + if (chainpp) { + *chainpp = inp + strlen(inp) + 1; + } + if ((flags & SMB_STRF_ANSIPATH) && smb_StoreAnsiFilenames) + OemToChar(inp, inp); return inp; +#ifdef SMB_UNICODE + } +#endif +} + +unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp, + unsigned char * str, + size_t * plen, int flags) +{ + size_t buffersize; + int align = 0; + + if (outp == NULL) { + /* we are only calculating the required size */ +#ifdef SMB_UNICODE + + if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) { + int nchars; + + nchars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str, -1, NULL, 0); + if (nchars == 0 && GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { + + if ((flags & SMB_STRF_ANSIPATH) && smb_StoreAnsiFilenames) + nchars = MultiByteToWideChar(1252 /* ANSI - Latin1 */, + 0, str, -1, NULL, 0); + else + nchars = MultiByteToWideChar(CP_OEMCP, + 0, str, -1, NULL, 0); + } + + if (nchars == 0) { + osi_Log2(smb_logp, "UnparseString: Can't convert string to Unicode [%S], GLE=%d", + osi_LogSaveString(smb_logp, str), + GetLastError()); + if (plen) + *plen = 0; + return NULL; + } + + if (plen) + *plen = sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENULL)? nchars - 1 : nchars); + + return (unsigned char *) 1; /* return TRUE if we are using unicode */ + } + else +#endif + { + /* Storing ANSI */ + size_t len; + + len = strlen(str); + if (plen) + *plen = ((flags & SMB_STRF_IGNORENULL)? len: len+1); + + return NULL; + } + } + + /* Number of bytes left in the buffer. */ + if (outp >= pktp->data && outp < pktp->data + sizeof(pktp->data)) { + align = ((outp - pktp->data) % 2); + buffersize = (pktp->data + sizeof(pktp->data)) - ((char *) outp); + } else { + align = (((size_t) outp) % 2); + buffersize = sizeof(pktp->data); + } + +#ifdef SMB_UNICODE + + if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) { + int nchars; + + if (align) + *outp++ = '\0'; + + if (*str == '\0') { + + if (buffersize < sizeof(wchar_t)) + return NULL; + + *((wchar_t *) outp) = L'\0'; + if (plen && !(flags & SMB_STRF_IGNORENULL)) + *plen += sizeof(wchar_t); + return outp + sizeof(wchar_t); + } + + nchars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str, -1, (wchar_t *) outp, buffersize); + if (nchars == 0 && GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { + + /* If we failed to translate the string from UTF-8 to + UTF-16, then chances are the string wasn't UTF-8 to + begin with. If StoreAnsiFileNames is set and this is + possibly an ANSI file name, we try assuming that the + source name is in ANSI. otherwise we try OEM. */ + + if ((flags & SMB_STRF_ANSIPATH) && smb_StoreAnsiFilenames) + nchars = MultiByteToWideChar(1252 /* ANSI - Latin1 */, + 0, str, -1, (wchar_t *) outp, buffersize); + else + nchars = MultiByteToWideChar(CP_OEMCP, + 0, str, -1, (wchar_t *) outp, buffersize); + } + + if (nchars == 0) { + /* Both 1252 and OEM should translate to Unicode without a + complaint. This is something else. */ + osi_Log2(smb_logp, "UnparseString: Can't convert string to Unicode [%S], GLE=%d", + osi_LogSaveString(smb_logp, str), + GetLastError()); + return NULL; + } + + if (plen) + *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENULL)? nchars - 1: nchars); + + return outp + sizeof(wchar_t) * nchars; + } + else +#endif + { + /* Storing ANSI */ + size_t len; + + len = strlen(str); len++; + if (len > buffersize) + return NULL; + + strcpy(outp, str); + if (plen) + *plen += ((flags & SMB_STRF_IGNORENULL)? len - 1: len); + + return outp + len; + } } unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp) @@ -2394,6 +2688,23 @@ unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *length return inp; } +unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp) +{ + int tlen; + + if (*inp++ != 0x1) return NULL; + tlen = inp[0] + (inp[1]<<8); + inp += 2; /* skip length field */ + + if (chainpp) { + *chainpp = inp + tlen; + } + + if (lengthp) *lengthp = tlen; + + return inp; +} + /* format a packet as a response */ void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op) { @@ -2427,6 +2738,10 @@ void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op outp->reb |= SMB_FLAGS_CANONICAL_PATHNAMES; #endif outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES; +#ifdef SMB_UNICODE + if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE) + outp->flg2 |= SMB_FLAGS2_UNICODE; +#endif /* copy fields in generic packet area */ op->wctp = &outp->wct; @@ -2831,6 +3146,7 @@ long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return CM_ERROR_BADOP; } +/* SMB_COM_ECHO */ long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned short EchoCount, i; @@ -2851,6 +3167,7 @@ long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return 0; } +/* SMB_COM_READ_RAW */ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { osi_hyper_t offset; @@ -3012,6 +3329,7 @@ long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t return 0; } +/* SMB_COM_NEGOTIATE */ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *namep; @@ -3131,7 +3449,8 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) * and NT Find * * and NT SMB's * * and raw mode - * and DFS */ + * and DFS + * and Unicode */ caps = NTNEGOTIATE_CAPABILITY_NTSTATUS | #ifdef DFS_SUPPORT NTNEGOTIATE_CAPABILITY_DFS | @@ -3146,6 +3465,12 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if ( smb_authType == SMB_AUTH_EXTENDED ) caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY; +#ifdef SMB_UNICODE + if ( smb_UseUnicode ) { + caps |= NTNEGOTIATE_CAPABILITY_UNICODE; + } +#endif + smb_SetSMBParmLong(outp, 9, caps); time(&unixTime); smb_SearchTimeFromUnixTime(&dosTime, unixTime); @@ -3521,6 +3846,7 @@ long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack return 0; } +/* SMB_COM_TREE_CONNECT */ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp) { smb_tid_t *tidp; @@ -3531,17 +3857,13 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * int shareFound; char *tp; char *pathp; - char *passwordp; cm_user_t *userp; osi_Log0(smb_logp, "SMB receive tree connect"); /* parse input parameters */ tp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); - passwordp = smb_ParseASCIIBlock(tp, &tp); + pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH); tp = strrchr(pathp, '\\'); if (!tp) return CM_ERROR_BADSMB; @@ -3575,23 +3897,6 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * return 0; } -unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp) -{ - int tlen; - - if (*inp++ != 0x1) return NULL; - tlen = inp[0] + (inp[1]<<8); - inp += 2; /* skip length field */ - - if (chainpp) { - *chainpp = inp + tlen; - } - - if (lengthp) *lengthp = tlen; - - return inp; -} - /* set maskp to the mask part of the incoming path. * Mask is 11 bytes long (8.3 with the dot elided). * Returns true if succeeds with a valid name, otherwise it does @@ -3709,6 +4014,10 @@ char *smb_FindMask(char *pathp) return pathp; /* no slash, return the entire path */ } +/* SMB_COM_SEARCH for a volume label + + (This is called from smb_ReceiveCoreSearchDir() and not an actual + dispatch function.) */ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned char *pathp; @@ -3722,10 +4031,9 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t /* pull pathname and stat block out of request */ tp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(tp, (char **) &tp); + pathp = smb_ParseASCIIBlock(inp, tp, (char **) &tp, + SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII); osi_assertx(pathp != NULL, "null path"); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen); osi_assertx(statBlockp != NULL, "null statBlock"); if (statLen == 0) { @@ -3768,6 +4076,9 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *tp++ = 0; *tp++ = 0; + /* The filename is a UCHAR buffer that is ASCII even if Unicode + was negotiated. */ + /* finally, null-terminated 8.3 pathname, which we set to AFS */ memset(tp, ' ', 13); strcpy(tp, "AFS"); @@ -3863,6 +4174,7 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp, return code; } +/* SMB_COM_SEARCH */ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { int attribute; @@ -3918,9 +4230,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou caseFold = CM_FLAG_CASEFOLD; tp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseASCIIBlock(inp, tp, &tp, + SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII); inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength); /* bail out if request looks bad */ @@ -4337,6 +4648,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou strncpy(op, actualName, 13); if (smb_StoreAnsiFilenames) CharToOem(op, op); + /* This is a UCHAR field, which is ASCII even if Unicode + is negotiated. */ /* Uppercase if requested by client */ if (!KNOWS_LONG_NAMES(inp)) @@ -4404,8 +4717,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou return code; } + /* verify that this is a valid path to a directory. I don't know why they * don't use the get file attributes call. + * + * SMB_COM_CHECK_DIRECTORY */ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { @@ -4422,11 +4738,9 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou cm_InitReq(&req); pathp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(pathp, NULL); + pathp = smb_ParseASCIIBlock(inp, pathp, NULL, SMB_STRF_ANSIPATH); if (!pathp) return CM_ERROR_BADFD; - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); osi_Log1(smb_logp, "SMB receive check path %s", osi_LogSaveString(smb_logp, pathp)); @@ -4489,6 +4803,7 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou return code; } +/* SMB_COM_SET_INFORMATION */ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *pathp; @@ -4510,11 +4825,9 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16); pathp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(pathp, NULL); + pathp = smb_ParseASCIIBlock(inp, pathp, NULL, SMB_STRF_ANSIPATH); if (!pathp) return CM_ERROR_BADSMB; - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x", dosTime, attribute); @@ -4604,6 +4917,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack return code; } + long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *pathp; @@ -4622,15 +4936,12 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack cm_InitReq(&req); pathp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(pathp, NULL); + pathp = smb_ParseASCIIBlock(inp, pathp, NULL, SMB_STRF_ANSIPATH); if (!pathp) return CM_ERROR_BADSMB; if (*pathp == 0) /* null path */ pathp = "\\"; - else - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); osi_Log1(smb_logp, "SMB receive getfile attributes path %s", osi_LogSaveString(smb_logp, pathp)); @@ -4770,6 +5081,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack return 0; } +/* SMB_COM_TREE_DISCONNECT */ long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_tid_t *tidp; @@ -4788,6 +5100,7 @@ long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_ return 0; } +/* SMB_COM_0PEN */ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_fid_t *fidp; @@ -4807,9 +5120,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) cm_InitReq(&req); pathp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(pathp, NULL); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseASCIIBlock(inp, pathp, NULL, SMB_STRF_ANSIPATH); osi_Log1(smb_logp, "SMB receive open file [%s]", osi_LogSaveString(smb_logp, pathp)); @@ -4994,6 +5305,7 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype return code; } +/* SMB_COM_DELETE */ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { int attribute; @@ -5015,9 +5327,7 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) attribute = smb_GetSMBParm(inp, 0); tp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH); osi_Log1(smb_logp, "SMB receive unlink %s", osi_LogSaveString(smb_logp, pathp)); @@ -5521,6 +5831,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp) return code; } +/* SMB_COM_RENAME */ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { @@ -5530,12 +5841,8 @@ smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) long code; tp = smb_GetSMBData(inp, NULL); - oldPathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(oldPathp,oldPathp); - newPathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(newPathp,newPathp); + oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH); + newPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH); osi_Log2(smb_logp, "smb rename [%s] to [%s]", osi_LogSaveString(smb_logp, oldPathp), @@ -5590,6 +5897,7 @@ int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper return 0; } + long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { long code = 0; @@ -5608,9 +5916,7 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou cm_InitReq(&req); tp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH); spacep = inp->spacep; smb_StripLastComponent(spacep->data, &lastNamep, pathp); @@ -5697,6 +6003,7 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou return code; } +/* SMB_COM_FLUSH */ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned short fid; @@ -6003,6 +6310,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp, return code; } +/* SMB_COM_CLOSE */ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned short fid; @@ -6465,6 +6773,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char return code; } +/* SMB_COM_WRITE */ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned short fd; @@ -6669,6 +6978,7 @@ long smb_ReceiveCoreWriteRawDummy(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t return 0; } +/* SMB_COM_WRITE_RAW */ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, raw_write_cont_t *rwcp) { osi_hyper_t offset; @@ -6847,6 +7157,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out return 0; } +/* SMB_COM_READ */ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { osi_hyper_t offset; @@ -6944,6 +7255,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return code; } +/* SMB_COM_CREATE_DIRECTORY */ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *pathp; @@ -6968,9 +7280,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp initialModeBits = 0777; tp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH); if (strcmp(pathp, "\\") == 0) return CM_ERROR_EXISTS; @@ -7063,6 +7373,7 @@ BOOL smb_IsLegalFilename(char *filename) return TRUE; } +/* SMB_COM_CREATE and SMB_COM_CREATE_NEW */ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *pathp; @@ -7098,9 +7409,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) initialModeBits &= ~0222; tp = smb_GetSMBData(inp, NULL); - pathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH); spacep = inp->spacep; smb_StripLastComponent(spacep->data, &lastNamep, pathp); @@ -7262,6 +7571,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return 0; } +/* SMB_COM_SEEK */ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { long code = 0; @@ -7436,9 +7746,11 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, /* Raw Write */ code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, rwcp); else { - osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d",opName,vcp,vcp->lana,vcp->lsn); + osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d", + opName,vcp,vcp->lana,vcp->lsn); code = (*(dp->procp)) (vcp, inp, outp); - osi_Log4(smb_logp,"Dispatch return code 0x%x vcp 0x%p lana %d lsn %d",code,vcp,vcp->lana,vcp->lsn); + osi_Log4(smb_logp,"Dispatch return code 0x%x vcp 0x%p lana %d lsn %d", + code,vcp,vcp->lana,vcp->lsn); #ifdef LOG_PACKET if ( code == CM_ERROR_BADSMB || code == CM_ERROR_BADOP ) @@ -7455,8 +7767,9 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, osi_Log3(smb_logp, "Request %s straddled session startup, " "took %d ms, ncb length %d", opName, newTime - oldTime, ncbp->ncb_length); } - } - else { + + FreeSMBStrings(inp); + } else { /* bad opcode, fail the request, after displaying it */ osi_Log1(smb_logp, "Received bad SMB req 0x%X", inp->inCom); #ifdef LOG_PACKET @@ -7976,8 +8289,10 @@ void smb_Server(VOID *parmp) smbp = (smb_t *)bufp->data; outbufp->flags = 0; +#ifndef NOTRACE __try { +#endif if (smbp->com == 0x1d) { /* Special handling for Write Raw */ raw_write_cont_t rwc; @@ -8015,9 +8330,11 @@ void smb_Server(VOID *parmp) /* TODO: what else needs to be serialized? */ smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL); } +#ifndef NOTRACE } __except( smb_ServerExceptionFilter() ) { } +#endif smb_concurrentCalls--; @@ -8316,6 +8633,7 @@ void smb_Listener(void *parmp) smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff); smbp->rcls = errClass; } + smb_SendPacket(vcp, outp); smb_FreePacket(outp); @@ -9290,6 +9608,7 @@ char *smb_GetSharename() void smb_LogPacket(smb_packet_t *packet) { BYTE *vp, *cp; + smb_t * smbp; unsigned length, paramlen, datalen, i, j; char buf[81]; char hex[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; @@ -9298,11 +9617,12 @@ void smb_LogPacket(smb_packet_t *packet) osi_Log0(smb_logp, "*** SMB packet dump ***"); + smbp = (smb_t *) packet->data; vp = (BYTE *) packet->data; - datalen = *((WORD*)(vp + (paramlen = ((unsigned)*(vp+20)) << 1))); - length = paramlen + 2 + datalen; - + paramlen = smbp->wct * 2; + datalen = *((WORD *) (smbp->vdata + paramlen)); + length = sizeof(*smbp) + paramlen + 1 + datalen; for (i=0;i < length; i+=16) { diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 86ec4a90e9..4565440098 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -64,6 +64,7 @@ typedef struct smb { #define KNOWS_LONG_NAMES(inp) ((((smb_t *)inp)->flg2 & SMB_FLAGS2_KNOWS_LONG_NAMES)?1:0) #define WANTS_DFS_PATHNAMES(inp) ((((smb_t *)inp)->flg2 & SMB_FLAGS2_DFS_PATHNAMES)?1:0) +#define WANTS_UNICODE(inp) ((((smb_t *)inp)->flg2 & SMB_FLAGS2_UNICODE)?1:0) /* Information Levels */ #define SMB_INFO_STANDARD 1 @@ -125,6 +126,8 @@ typedef struct smb { #define SMB_PACKETSIZE 32768 /* was 8400 */ /* raw mode is considered obsolete and cannot be used with message signing */ #define SMB_MAXRAWSIZE 65536 +/* max STRING characters per packet per request */ +#define SMB_STRINGBUFSIZE 4096 /* Negotiate protocol constants */ /* Security */ @@ -186,6 +189,7 @@ typedef struct smb_packet { unsigned char oddByte; unsigned short ncb_length; unsigned char flags; + cm_space_t *stringsp; /* decoded strings from this packet */ } smb_packet_t; /* smb_packet flags */ @@ -242,6 +246,7 @@ typedef struct smb_vc { #define SMB_VCFLAG_SESSX_RCVD 0x40 /* we received at least one session setups on this vc */ #define SMB_VCFLAG_AUTH_IN_PROGRESS 0x80 /* a SMB NT extended authentication is in progress */ #define SMB_VCFLAG_CLEAN_IN_PROGRESS 0x100 +#define SMB_VCFLAG_USEUNICODE 0x200 /* une UNICODE for STRING fields (NTLM 0.12 or later) */ /* one per user session */ typedef struct smb_user { @@ -338,11 +343,13 @@ typedef struct smb_ioctl { /* uid pointer */ smb_user_t *uidp; + } smb_ioctl_t; /* flags for smb_ioctl_t */ #define SMB_IOCTLFLAG_DATAIN 1 /* reading data from client to server */ #define SMB_IOCTLFLAG_LOGON 2 /* got tokens from integrated logon */ +#define SMB_IOCTLFLAG_USEUTF8 4 /* this request is using UTF-8 strings */ /* one per file ID; these are really file descriptors */ typedef struct smb_fid { @@ -622,7 +629,30 @@ extern void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmVa extern void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp); -extern unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp); +#define SMB_STRF_FORCEASCII (1<<0) +#define SMB_STRF_ANSIPATH (1<<1) +#define SMB_STRF_IGNORENULL (1<<2) + +extern unsigned char *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp, + char **chainpp, int flags); + +extern unsigned char *smb_ParseString(smb_packet_t * pktp, unsigned char * inp, + char ** chainpp, int flags); + +extern unsigned char *smb_ParseStringBuf(const unsigned char * bufbase, + cm_space_t ** stringspp, + unsigned char *inp, size_t *pcb_max, + char **chainpp, int flags); + +extern unsigned char *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp, + size_t cb, char ** chainpp, int flags); + +extern unsigned char *smb_ParseStringCch(smb_packet_t * pktp, unsigned char * inp, + size_t cch, char ** chainpp, int flags); + +extern unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp, + unsigned char * str, + size_t * plen, int flags); extern unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp); @@ -678,6 +708,7 @@ extern char smb_ServerLanManager[]; extern int smb_ServerLanManagerLength; extern GUID smb_ServerGUID; extern LSA_STRING smb_lsaLogonOrigin; +extern LONG smb_UseUnicode; /* used for getting a challenge for SMB auth */ typedef struct _MSV1_0_LM20_CHALLENGE_REQUEST { @@ -709,8 +740,6 @@ extern int smb_ChainFID(int fid, smb_packet_t *inp); extern unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp); -extern unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp); - extern unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp); extern int smb_SUser(cm_user_t *userp); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 27c6e1a5c2..fa40caeb18 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -133,15 +133,6 @@ int smb_V3IsStarMask(char *maskp) return 0; } -unsigned char *smb_ParseString(unsigned char *inp, char **chainpp) -{ - if (chainpp) { - /* skip over null-terminated string */ - *chainpp = inp + strlen(inp) + 1; - } - return inp; -} - void OutputDebugF(char * format, ...) { va_list args; int len; @@ -676,6 +667,7 @@ long smb_GetNormalizedUsername(char * usern, const char * accountName, const cha * sending a session setup packet, which means that we can't rely on a * UID in subsequent packets. Though in practice we get one anyway. */ +/* SMB_COM_SESSION_SETUP_ANDX */ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *tp; @@ -711,21 +703,23 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * code = smb_AuthenticateUserExt(vcp, usern, secBlobIn, secBlobInLength, &secBlobOut, &secBlobOutLength); if (code == CM_ERROR_GSSCONTINUE) { + size_t cb_data = 0; + smb_SetSMBParm(outp, 2, 0); smb_SetSMBParm(outp, 3, secBlobOutLength); - smb_SetSMBDataLength(outp, secBlobOutLength + smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength); + tp = smb_GetSMBData(outp, NULL); if (secBlobOutLength) { memcpy(tp, secBlobOut, secBlobOutLength); free(secBlobOut); tp += secBlobOutLength; + cb_data += secBlobOutLength; } - memcpy(tp,smb_ServerOS,smb_ServerOSLength); - tp += smb_ServerOSLength; - memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength); - tp += smb_ServerLanManagerLength; - memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength); - tp += smb_ServerDomainNameLength; + tp = smb_UnparseString(outp, tp, smb_ServerOS, &cb_data, 0); + tp = smb_UnparseString(outp, tp, smb_ServerLanManager, &cb_data, 0); + tp = smb_UnparseString(outp, tp, smb_ServerDomainName, &cb_data, 0); + + smb_SetSMBDataLength(outp, cb_data); } /* TODO: handle return code and continue auth. Also free secBlobOut if applicable. */ @@ -754,8 +748,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * csPwd = tp; tp += csPwdLength; - accountName = smb_ParseString(tp, &tp); - primaryDomain = smb_ParseString(tp, NULL); + accountName = smb_ParseString(inp, tp, &tp, 0); + primaryDomain = smb_ParseString(inp, tp, NULL, 0); OutputDebugF("Account Name: %s",accountName); OutputDebugF("Primary Domain: %s", primaryDomain); @@ -802,8 +796,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * ciPwd = tp; tp += ciPwdLength; - accountName = smb_ParseString(tp, &tp); - primaryDomain = smb_ParseString(tp, NULL); + accountName = smb_ParseString(inp, tp, &tp, 0); + primaryDomain = smb_ParseString(inp, tp, NULL, 0); OutputDebugF("Account Name: %s",accountName); OutputDebugF("Primary Domain: %s", primaryDomain); @@ -836,6 +830,12 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * if (caps & NTNEGOTIATE_CAPABILITY_NTSTATUS) { vcp->flags |= SMB_VCFLAG_STATUS32; } + +#ifdef SMB_UNICODE + if ((caps & NTNEGOTIATE_CAPABILITY_UNICODE) && smb_UseUnicode) { + vcp->flags |= SMB_VCFLAG_USEUNICODE; + } +#endif lock_ReleaseMutex(&vcp->mx); } @@ -918,33 +918,37 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * if (vcp->flags & SMB_VCFLAG_USENT) { if (smb_authType == SMB_AUTH_EXTENDED) { + size_t cb_data = 0; + smb_SetSMBParm(outp, 3, secBlobOutLength); - smb_SetSMBDataLength(outp, secBlobOutLength + smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength); + tp = smb_GetSMBData(outp, NULL); if (secBlobOutLength) { memcpy(tp, secBlobOut, secBlobOutLength); free(secBlobOut); tp += secBlobOutLength; + cb_data += secBlobOutLength; } - memcpy(tp,smb_ServerOS,smb_ServerOSLength); - tp += smb_ServerOSLength; - memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength); - tp += smb_ServerLanManagerLength; - memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength); - tp += smb_ServerDomainNameLength; + + tp = smb_UnparseString(outp, tp, smb_ServerOS, &cb_data, 0); + tp = smb_UnparseString(outp, tp, smb_ServerLanManager, &cb_data, 0); + tp = smb_UnparseString(outp, tp, smb_ServerDomainName, &cb_data, 0); + + smb_SetSMBDataLength(outp, cb_data); } else { smb_SetSMBDataLength(outp, 0); } } else { if (smb_authType == SMB_AUTH_EXTENDED) { - smb_SetSMBDataLength(outp, smb_ServerOSLength + smb_ServerLanManagerLength + smb_ServerDomainNameLength); + size_t cb_data = 0; + tp = smb_GetSMBData(outp, NULL); - memcpy(tp,smb_ServerOS,smb_ServerOSLength); - tp += smb_ServerOSLength; - memcpy(tp,smb_ServerLanManager,smb_ServerLanManagerLength); - tp += smb_ServerLanManagerLength; - memcpy(tp,smb_ServerDomainName,smb_ServerDomainNameLength); - tp += smb_ServerDomainNameLength; + + tp = smb_UnparseString(outp, tp, smb_ServerOS, &cb_data, 0); + tp = smb_UnparseString(outp, tp, smb_ServerLanManager, &cb_data, 0); + tp = smb_UnparseString(outp, tp, smb_ServerDomainName, &cb_data, 0); + + smb_SetSMBDataLength(outp, cb_data); } else { smb_SetSMBDataLength(outp, 0); } @@ -953,6 +957,7 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * return 0; } +/* SMB_COM_LOGOFF_ANDX */ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_user_t *uidp; @@ -1000,6 +1005,7 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou #define SMB_SUPPORT_SEARCH_BITS 0x0001 #define SMB_SHARE_IS_IN_DFS 0x0002 +/* SMB_COM_TREE_CONNECT_ANDX */ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_tid_t *tidp; @@ -1019,11 +1025,9 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o /* parse input parameters */ tp = smb_GetSMBData(inp, NULL); - passwordp = smb_ParseString(tp, &tp); - pathp = smb_ParseString(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); - servicep = smb_ParseString(tp, &tp); + passwordp = smb_ParseString(inp, tp, &tp, SMB_STRF_FORCEASCII); + pathp = smb_ParseString(inp, tp, &tp, SMB_STRF_ANSIPATH); + servicep = smb_ParseString(inp, tp, &tp, SMB_STRF_FORCEASCII); tp = strrchr(pathp, '\\'); if (!tp) { @@ -1031,9 +1035,10 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o } strcpy(shareName, tp+1); - osi_Log2(smb_logp, "Tree connect pathp[%s] shareName[%s]", + osi_Log3(smb_logp, "Tree connect pathp[%s] shareName[%s] service[%s]", osi_LogSaveString(smb_logp, pathp), - osi_LogSaveString(smb_logp, shareName)); + osi_LogSaveString(smb_logp, shareName), + osi_LogSaveString(smb_logp, servicep)); if (strcmp(servicep, "IPC") == 0 || strcmp(shareName, "IPC$") == 0) { #ifndef NO_IPC @@ -1104,18 +1109,16 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o ((smb_t *)inp)->tid = newTid; tp = smb_GetSMBData(outp, NULL); if (!ipc) { - /* XXX - why is this a drive letter? */ - *tp++ = 'A'; - *tp++ = ':'; - *tp++ = 0; - *tp++ = 'A'; - *tp++ = 'F'; - *tp++ = 'S'; - *tp++ = 0; - smb_SetSMBDataLength(outp, 7); + size_t cb_data = 0; + + tp = smb_UnparseString(outp, tp, "A:", &cb_data, SMB_STRF_FORCEASCII); + tp = smb_UnparseString(outp, tp, "AFS", &cb_data, 0); + smb_SetSMBDataLength(outp, cb_data); } else { - strcpy(tp, "IPC"); - smb_SetSMBDataLength(outp, 4); + size_t cb_data = 0; + + tp = smb_UnparseString(outp, tp, "IPC", &cb_data, SMB_STRF_FORCEASCII); + smb_SetSMBDataLength(outp, cb_data); } osi_Log1(smb_logp, "SMB3 tree connect created ID %d", newTid); @@ -1167,6 +1170,10 @@ smb_tran2Packet_t *smb_NewTran2Packet(smb_vc_t *vcp, smb_packet_t *inp, tp->com = 0x32; } tp->flags |= SMB_TRAN2PFLAG_ALLOC; +#ifdef SMB_UNICODE + if (WANTS_UNICODE(inp) && (vcp->flags & SMB_VCFLAG_USEUNICODE)) + tp->flags |= SMB_TRAN2PFLAG_USEUNICODE; +#endif return tp; } @@ -1226,9 +1233,37 @@ void smb_FreeTran2Packet(smb_tran2Packet_t *t2p) if (t2p->datap) free(t2p->datap); } + while (t2p->stringsp) { + cm_space_t * ns; + + ns = t2p->stringsp; + t2p->stringsp = ns->nextp; + cm_FreeSpace(ns); + } free(t2p); } +unsigned char *smb_ParseStringT2Parm(smb_tran2Packet_t * p, unsigned char * inp, + char ** chainpp, int flags) +{ + size_t cb; + +#ifdef SMB_UNICODE + if (!(p->flags & SMB_TRAN2PFLAG_USEUNICODE)) + flags |= SMB_STRF_FORCEASCII; +#endif + + cb = p->totalParms - (inp - (unsigned char *)p->parmsp); + if (inp < (unsigned char *) p->parmsp || + inp > ((unsigned char *) p->parmsp) + p->totalParms) { + DebugBreak(); + cb = p->totalParms; + } + + return smb_ParseStringBuf((unsigned char *) p->parmsp, &p->stringsp, + inp, &cb, chainpp, flags); +} + /* called with a VC, an input packet to respond to, and an error code. * sends an error response. */ @@ -1331,6 +1366,8 @@ void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp smb_SendPacket(vcp, tp); } + +/* SMB_COM_TRANSACTION and SMB_COM_TRANSACTION_SECONDARY */ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_tran2Packet_t *asp; @@ -1453,31 +1490,32 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return 0; } -/* ANSI versions. The unicode versions support arbitrary length - share names, but we don't support unicode yet. */ +/* ANSI versions. */ + +#pragma pack(push, 1) typedef struct smb_rap_share_info_0 { - char shi0_netname[13]; + BYTE shi0_netname[13]; } smb_rap_share_info_0_t; typedef struct smb_rap_share_info_1 { - char shi1_netname[13]; - char shi1_pad; + BYTE shi1_netname[13]; + BYTE shi1_pad; WORD shi1_type; DWORD shi1_remark; /* char *shi1_remark; data offset */ } smb_rap_share_info_1_t; typedef struct smb_rap_share_info_2 { - char shi2_netname[13]; - char shi2_pad; - unsigned short shi2_type; + BYTE shi2_netname[13]; + BYTE shi2_pad; + WORD shi2_type; DWORD shi2_remark; /* char *shi2_remark; data offset */ - unsigned short shi2_permissions; - unsigned short shi2_max_uses; - unsigned short shi2_current_uses; + WORD shi2_permissions; + WORD shi2_max_uses; + WORD shi2_current_uses; DWORD shi2_path; /* char *shi2_path; data offset */ - unsigned short shi2_passwd[9]; - unsigned short shi2_pad2; + WORD shi2_passwd[9]; + WORD shi2_pad2; } smb_rap_share_info_2_t; #define SMB_RAP_MAX_SHARES 512 @@ -1488,6 +1526,8 @@ typedef struct smb_rap_share_list { smb_rap_share_info_0_t * shares; } smb_rap_share_list_t; +#pragma pack(pop) + int smb_rapCollectSharesProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp) { smb_rap_share_list_t * sp; char * name; @@ -1510,6 +1550,7 @@ int smb_rapCollectSharesProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp return 0; } +/* RAP NetShareEnumRequest */ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { smb_tran2Packet_t *outp; @@ -1540,8 +1581,18 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_ osi_hyper_t thyper; tp = p->parmsp + 1; /* skip over function number (always 0) */ - (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over parm descriptor */ - (void) smb_ParseString((char *) tp, (char **) &tp); /* skip over data descriptor */ + + { + char * cdescp; + + cdescp = smb_ParseStringT2Parm(p, (char *) tp, (char **) &tp, SMB_STRF_FORCEASCII); + if (strcmp(cdescp, "WrLeh")) + return CM_ERROR_INVAL; + cdescp = smb_ParseStringT2Parm(p, (char *) tp, (char **) &tp, SMB_STRF_FORCEASCII); + if (strcmp(cdescp, "B13BWz")) + return CM_ERROR_INVAL; + } + infoLevel = tp[0]; bufsize = tp[1]; @@ -1549,6 +1600,18 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_ return CM_ERROR_INVAL; } + /* We are supposed to use the same ASCII data structure even if + Unicode is negotiated, which ultimately means that the share + names that we return must be at most 13 characters in length, + including the NULL terminator. + + The RAP specification states that shares with names longer than + 12 characters should not be included in the enumeration. + However, since we support prefix cell references and since many + cell names are going to exceed 12 characters, we lie and send + the first 12 characters. + */ + /* first figure out how many shares there are */ rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_QUERY_VALUE, &hkParam); @@ -1624,8 +1687,10 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_ for (dw=0; dw < nRegShares && cshare < nSharesRet; dw++) { len = sizeof(thisShare); rv = RegEnumValue(hkSubmount, dw, thisShare, &len, NULL, NULL, NULL, NULL); - if (rv == ERROR_SUCCESS && strlen(thisShare) && (!allSubmount || stricmp(thisShare,"all"))) { - strncpy(shares[cshare].shi1_netname, thisShare, sizeof(shares->shi1_netname)-1); + if (rv == ERROR_SUCCESS && + strlen(thisShare) && (!allSubmount || stricmp(thisShare,"all"))) { + strncpy(shares[cshare].shi1_netname, thisShare, + sizeof(shares->shi1_netname)-1); shares[cshare].shi1_netname[sizeof(shares->shi1_netname)-1] = 0; /* unfortunate truncation */ shares[cshare].shi1_remark = (DWORD)(cstrp - outp->datap); cshare++; @@ -1673,6 +1738,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_ return code; } +/* RAP NetShareGetInfo */ long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { smb_tran2Packet_t *outp; @@ -1696,9 +1762,24 @@ long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack cm_InitReq(&req); tp = p->parmsp + 1; /* skip over function number (always 1) */ - (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over param descriptor */ - (void) smb_ParseString( (char *) tp, (char **) &tp); /* skip over data descriptor */ - shareName = smb_ParseString( (char *) tp, (char **) &tp); + + { + char * cdescp; + + cdescp = smb_ParseStringT2Parm(p, (char *) tp, (char **) &tp, SMB_STRF_FORCEASCII); + if (strcmp(cdescp, "zWrLh")) + + return CM_ERROR_INVAL; + + cdescp = smb_ParseStringT2Parm(p, (char *) tp, (char **) &tp, SMB_STRF_FORCEASCII); + if (strcmp(cdescp, "B13") && + strcmp(cdescp, "B13BWz") && + strcmp(cdescp, "B13BWzWWWzB9B")) + + return CM_ERROR_INVAL; + } + shareName = smb_ParseStringT2Parm(p, (char *) tp, (char **) &tp, SMB_STRF_FORCEASCII); + infoLevel = *tp++; bufsize = *tp++; @@ -1793,16 +1874,19 @@ long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack return code; } +#pragma pack(push, 1) + typedef struct smb_rap_wksta_info_10 { DWORD wki10_computername; /*char *wki10_computername;*/ DWORD wki10_username; /* char *wki10_username; */ DWORD wki10_langroup; /* char *wki10_langroup;*/ - unsigned char wki10_ver_major; - unsigned char wki10_ver_minor; + BYTE wki10_ver_major; + BYTE wki10_ver_minor; DWORD wki10_logon_domain; /*char *wki10_logon_domain;*/ DWORD wki10_oth_domains; /* char *wki10_oth_domains;*/ } smb_rap_wksta_info_10_t; +#pragma pack(pop) long smb_ReceiveRAPNetWkstaGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { @@ -1818,8 +1902,20 @@ long smb_ReceiveRAPNetWkstaGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack smb_user_t *uidp; tp = p->parmsp + 1; /* Skip over function number */ - (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */ - (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */ + + { + char * cdescp; + + cdescp = smb_ParseStringT2Parm(p, (unsigned char*) tp, (char **) &tp, + SMB_STRF_FORCEASCII); + if (strcmp(cdescp, "WrLh")) + return CM_ERROR_INVAL; + cdescp = smb_ParseStringT2Parm(p, (unsigned char*) tp, (char **) &tp, + SMB_STRF_FORCEASCII); + if (strcmp(cdescp, "zzzBBzz")) + return CM_ERROR_INVAL; + } + infoLevel = *tp++; bufsize = *tp++; @@ -1885,18 +1981,22 @@ long smb_ReceiveRAPNetWkstaGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack return code; } +#pragma pack(push, 1) + typedef struct smb_rap_server_info_0 { - char sv0_name[16]; + BYTE sv0_name[16]; } smb_rap_server_info_0_t; typedef struct smb_rap_server_info_1 { - char sv1_name[16]; - char sv1_version_major; - char sv1_version_minor; - unsigned long sv1_type; - DWORD *sv1_comment_or_master_browser; /* char *sv1_comment_or_master_browser;*/ + BYTE sv1_name[16]; + BYTE sv1_version_major; + BYTE sv1_version_minor; + DWORD sv1_type; + DWORD sv1_comment_or_master_browser; /* char *sv1_comment_or_master_browser;*/ } smb_rap_server_info_1_t; +#pragma pack(pop) + char smb_ServerComment[] = "OpenAFS Client"; int smb_ServerCommentLen = sizeof(smb_ServerComment); @@ -1918,8 +2018,21 @@ long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pac char * cstrp; tp = p->parmsp + 1; /* Skip over function number */ - (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */ - (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */ + + { + char * cdescp; + + cdescp = smb_ParseStringT2Parm(p, (unsigned char*) tp, (char **) &tp, + SMB_STRF_FORCEASCII); + if (strcmp(cdescp, "WrLh")) + return CM_ERROR_INVAL; + cdescp = smb_ParseStringT2Parm(p, (unsigned char*) tp, (char **) &tp, + SMB_STRF_FORCEASCII); + if (strcmp(cdescp, "B16") || + strcmp(cdescp, "B16BBDz")) + return CM_ERROR_INVAL; + } + infoLevel = *tp++; bufsize = *tp++; @@ -1954,7 +2067,7 @@ long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pac info1->sv1_version_major = 5; info1->sv1_version_minor = 1; - info1->sv1_comment_or_master_browser = (DWORD *) (cstrp - outp->datap); + info1->sv1_comment_or_master_browser = (DWORD) (cstrp - outp->datap); strcpy(cstrp, smb_ServerComment); @@ -1973,6 +2086,7 @@ long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pac return code; } +/* SMB_COM_TRANSACTION2 and SMB_COM_TRANSACTION2_SECONDARY */ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_tran2Packet_t *asp; @@ -2091,6 +2205,7 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return 0; } +/* TRANS2_OPEN2 */ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { char *pathp; @@ -2139,9 +2254,8 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) if (attributes & SMB_ATTR_READONLY) initialModeBits &= ~0222; - pathp = (char *) (&p->parmsp[14]); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[14]), NULL, + SMB_STRF_ANSIPATH); outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0); @@ -2488,44 +2602,21 @@ long smb_ReceiveTran2QFSInfoFid(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_ return CM_ERROR_BAD_LEVEL; } +/* TRANS2_QUERY_FS_INFORMATION */ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { smb_tran2Packet_t *outp; smb_tran2QFSInfo_t qi; int responseSize; - static char FSname[8] = {'A', 0, 'F', 0, 'S', 0, 0, 0}; + size_t sz = 0; osi_Log1(smb_logp, "T2 QFSInfo type 0x%x", p->parmsp[0]); - switch (p->parmsp[0]) { - case SMB_INFO_ALLOCATION: - responseSize = sizeof(qi.u.allocInfo); - break; - case SMB_INFO_VOLUME: - responseSize = sizeof(qi.u.volumeInfo); - break; - case SMB_QUERY_FS_VOLUME_INFO: - responseSize = sizeof(qi.u.FSvolumeInfo); - break; - case SMB_QUERY_FS_SIZE_INFO: - responseSize = sizeof(qi.u.FSsizeInfo); - break; - case SMB_QUERY_FS_DEVICE_INFO: - responseSize = sizeof(qi.u.FSdeviceInfo); - break; - case SMB_QUERY_FS_ATTRIBUTE_INFO: - responseSize = sizeof(qi.u.FSattributeInfo); - break; - case SMB_INFO_UNIX: /* CIFS Unix Info */ - case SMB_INFO_MACOS: /* Mac FS Info */ - default: - return CM_ERROR_BADOP; - } - - outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, responseSize); switch (p->parmsp[0]) { case SMB_INFO_ALLOCATION: /* alloc info */ + responseSize = sizeof(qi.u.allocInfo); + qi.u.allocInfo.FSID = 0; qi.u.allocInfo.sectorsPerAllocUnit = 1; qi.u.allocInfo.totalAllocUnits = 0x7fffffff; @@ -2535,23 +2626,34 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t * case SMB_INFO_VOLUME: /* volume info */ - qi.u.volumeInfo.vsn = 1234; - qi.u.volumeInfo.vnCount = 4; + qi.u.volumeInfo.vsn = 1234; /* Volume serial number */ + qi.u.volumeInfo.vnCount = 4; /* Number of characters in label (AFS\0)*/ + /* we're supposed to pad it out with zeroes to the end */ memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label)); - memcpy(qi.u.volumeInfo.label, "AFS", 4); + smb_UnparseString(op, qi.u.volumeInfo.label, "AFS", &sz, 0); + + responseSize = sizeof(unsigned long) + sizeof(char) + max(12, sz); break; case SMB_QUERY_FS_VOLUME_INFO: /* FS volume info */ - memset((char *)&qi.u.FSvolumeInfo.vct, 0, 4); + responseSize = sizeof(qi.u.FSvolumeInfo); + + { + FILETIME ft = {0x832cf000, 0x01abfcc4}; /* October 1, 1982 00:00:00 +0600 */ + memcpy(&qi.u.FSvolumeInfo.vct, &ft, sizeof(ft)); + } + qi.u.FSvolumeInfo.vsn = 1234; - qi.u.FSvolumeInfo.vnCount = 8; - memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0\0", 8); + qi.u.FSvolumeInfo.vnCount = 8; /* This is always in Unicode */ + memcpy(qi.u.FSvolumeInfo.label, L"AFS", sizeof(L"AFS")); break; case SMB_QUERY_FS_SIZE_INFO: /* FS size info */ + responseSize = sizeof(qi.u.FSsizeInfo); + qi.u.FSsizeInfo.totalAllocUnits.HighPart = 0; qi.u.FSsizeInfo.totalAllocUnits.LowPart= 0x7fffffff; qi.u.FSsizeInfo.availAllocUnits.HighPart = 0; @@ -2562,12 +2664,15 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t * case SMB_QUERY_FS_DEVICE_INFO: /* FS device info */ + responseSize = sizeof(qi.u.FSdeviceInfo); + qi.u.FSdeviceInfo.devType = 0x14; /* network file system */ qi.u.FSdeviceInfo.characteristics = 0x50; /* remote, virtual */ break; case SMB_QUERY_FS_ATTRIBUTE_INFO: /* FS attribute info */ + /* attributes, defined in WINNT.H: * FILE_CASE_SENSITIVE_SEARCH 0x1 * FILE_CASE_PRESERVED_NAMES 0x2 @@ -2578,12 +2683,35 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t * * despite our protestations to the contrary. */ qi.u.FSattributeInfo.attributes = 0x4003; + /* The maxCompLength is supposed to be in bytes */ +#ifdef SMB_UNICODE + if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE) + qi.u.FSattributeInfo.maxCompLength = MAX_PATH * sizeof(wchar_t); + else { +#endif qi.u.FSattributeInfo.maxCompLength = MAX_PATH; - qi.u.FSattributeInfo.FSnameLength = sizeof(FSname); - memcpy(qi.u.FSattributeInfo.FSname, FSname, sizeof(FSname)); +#ifdef SMB_UNICODE + } +#endif + smb_UnparseString(op, qi.u.FSattributeInfo.FSname, "AFS", &sz, 0); + qi.u.FSattributeInfo.FSnameLength = sz; + + responseSize = + sizeof(qi.u.FSattributeInfo.attributes) + + sizeof(qi.u.FSattributeInfo.maxCompLength) + + sizeof(qi.u.FSattributeInfo.FSnameLength) + + sz; + break; + + case SMB_INFO_UNIX: /* CIFS Unix Info */ + case SMB_INFO_MACOS: /* Mac FS Info */ + default: + return CM_ERROR_BADOP; } + outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, responseSize); + /* copy out return data, and set corresponding sizes */ outp->totalParms = 0; outp->totalData = responseSize; @@ -2678,6 +2806,7 @@ long cm_GetShortName(char *pathp, cm_user_t *userp, cm_req_t *reqp, return code; } +/* TRANS2_QUERY_PATH_INFORMATION */ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx) { smb_tran2Packet_t *outp; @@ -2689,7 +2818,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t unsigned short attributes; unsigned long extAttributes; char shortName[13]; - unsigned int len; + size_t len; cm_user_t *userp; cm_space_t *spacep; cm_scache_t *scp, *dscp; @@ -2729,9 +2858,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return 0; } - pathp = (char *)(&p->parmsp[3]); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[3]), NULL, SMB_STRF_ANSIPATH); osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path %s", infoLevel, osi_LogSaveString(smb_logp, pathp)); @@ -2867,6 +2994,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t lock_ConvertWToR(&scp->rw); + len = 0; + /* now we have the status in the cache entry, and everything is locked. * Marshall the output data. */ @@ -2874,20 +3003,19 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO) { code = cm_GetShortName(pathp, userp, &req, tidPathp, scp->fid.vnode, shortName, - (size_t *) &len); + &len); if (code) { goto done; } - qpi.u.QPfileAltNameInfo.fileNameLength = (len + 1) * 2; - mbstowcs((unsigned short *)qpi.u.QPfileAltNameInfo.fileName, shortName, len + 1); + smb_UnparseString(opx, qpi.u.QPfileAltNameInfo.fileName, shortName, &len, 0); + qpi.u.QPfileAltNameInfo.fileNameLength = len; goto done; } else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) { - len = (unsigned int)strlen(lastComp); - qpi.u.QPfileNameInfo.fileNameLength = (len + 1) * 2; - mbstowcs((unsigned short *)qpi.u.QPfileNameInfo.fileName, lastComp, len + 1); + smb_UnparseString(opx, qpi.u.QPfileNameInfo.fileName, lastComp, &len, 0); + qpi.u.QPfileNameInfo.fileNameLength = len; goto done; } @@ -2963,9 +3091,9 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t qpi.u.QPfileAllInfo.currentByteOffset.LowPart = 0; qpi.u.QPfileAllInfo.mode = 0; qpi.u.QPfileAllInfo.alignmentRequirement = 0; - len = (unsigned int)strlen(lastComp); - qpi.u.QPfileAllInfo.fileNameLength = (len + 1) * 2; - mbstowcs((unsigned short *)qpi.u.QPfileAllInfo.fileName, lastComp, len + 1); + + smb_UnparseString(opx, qpi.u.QPfileAllInfo.fileName, lastComp, &len, 0); + qpi.u.QPfileAllInfo.fileNameLength = len; } /* send and free the packets */ @@ -2985,6 +3113,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return 0; } +/* TRANS2_SET_PATH_INFORMATION */ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx) { #if 0 @@ -3018,9 +3147,8 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet return 0; } - pathp = (char *)(&p->parmsp[3]); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[3]), NULL, SMB_STRF_ANSIPATH); + osi_Log2(smb_logp, "T2 SetPathInfo infolevel 0x%x path %s", infoLevel, osi_LogSaveString(smb_logp, pathp)); @@ -3212,6 +3340,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet #endif } +/* TRANS2_QUERY_FILE_INFORMATION */ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx) { smb_tran2Packet_t *outp; @@ -3322,7 +3451,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t qfi.u.QFeaInfo.eaSize = 0; } else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) { - unsigned long len; + size_t len = 0; char *name; lock_ReleaseRead(&scp->rw); @@ -3333,10 +3462,10 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t else name = "\\"; /* probably can't happen */ lock_ReleaseMutex(&fidp->mx); - len = (unsigned long)strlen(name); - outp->totalData = ((len+1)*2) + 4; /* this is actually what we want to return */ - qfi.u.QFfileNameInfo.fileNameLength = (len + 1) * 2; - mbstowcs((unsigned short *)qfi.u.QFfileNameInfo.fileName, name, len + 1); + + smb_UnparseString(opx, qfi.u.QFfileNameInfo.fileName, name, &len, 0); + outp->totalData = len + 4; /* this is actually what we want to return */ + qfi.u.QFfileNameInfo.fileNameLength = len; } /* send and free the packets */ @@ -3359,6 +3488,8 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return 0; } + +/* TRANS2_SET_FILE_INFORMATION */ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx) { long code = 0; @@ -3547,6 +3678,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet return 0; } +/* TRANS2_FSCTL */ long smb_ReceiveTran2FSCTL(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { @@ -3554,6 +3686,7 @@ smb_ReceiveTran2FSCTL(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) return CM_ERROR_BADOP; } +/* TRANS2_IOCTL2 */ long smb_ReceiveTran2IOCTL(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { @@ -3561,6 +3694,7 @@ smb_ReceiveTran2IOCTL(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) return CM_ERROR_BADOP; } +/* TRANS2_FIND_NOTIFY_FIRST */ long smb_ReceiveTran2FindNotifyFirst(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { @@ -3568,6 +3702,7 @@ smb_ReceiveTran2FindNotifyFirst(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_ return CM_ERROR_BADOP; } +/* TRANS2_FIND_NOTIFY_NEXT */ long smb_ReceiveTran2FindNotifyNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { @@ -3575,6 +3710,7 @@ smb_ReceiveTran2FindNotifyNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return CM_ERROR_BADOP; } +/* TRANS2_CREATE_DIRECTORY */ long smb_ReceiveTran2CreateDirectory(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { @@ -3582,6 +3718,7 @@ smb_ReceiveTran2CreateDirectory(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_ return CM_ERROR_BADOP; } +/* TRANS2_SESSION_SETUP */ long smb_ReceiveTran2SessionSetup(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { @@ -3599,6 +3736,7 @@ struct smb_v2_referral { USHORT NetworkAddressOffset; }; +/* TRANS2_GET_DFS_REFERRAL */ long smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { @@ -3805,6 +3943,7 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t #endif /* DFS_SUPPORT */ } +/* TRANS2_REPORT_DFS_INCONSISTENCY */ long smb_ReceiveTran2ReportDFSInconsistency(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { @@ -3830,10 +3969,8 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, long code = 0; cm_scache_t *scp; cm_scache_t *targetScp; /* target if scp is a symlink */ - char *dptr; afs_uint32 dosTime; FILETIME ft; - int shortTemp; unsigned short attr; unsigned long lattr; smb_dirListPatch_t *patchp; @@ -3876,37 +4013,27 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, if (mustFake || code) { lock_ReleaseWrite(&scp->rw); - dptr = patchp->dptr; - /* Plug in fake timestamps. A time stamp of 0 causes 'invalid parameter' errors in the client. */ if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) { + smb_V3FileAttrsLong * fa = (smb_V3FileAttrsLong *) patchp->dptr; + /* 1969-12-31 23:59:59 +00 */ ft.dwHighDateTime = 0x19DB200; ft.dwLowDateTime = 0x5BB78980; /* copy to Creation Time */ - *((FILETIME *)dptr) = ft; - dptr += 8; - - /* copy to Last Access Time */ - *((FILETIME *)dptr) = ft; - dptr += 8; - - /* copy to Last Write Time */ - *((FILETIME *)dptr) = ft; - dptr += 8; - - /* copy to Change Time */ - *((FILETIME *)dptr) = ft; - dptr += 24; + fa->creationTime = ft; + fa->lastAccessTime = ft; + fa->lastWriteTime = ft; + fa->lastChangeTime = ft; switch (scp->fileType) { case CM_SCACHETYPE_DIRECTORY: case CM_SCACHETYPE_MOUNTPOINT: case CM_SCACHETYPE_SYMLINK: case CM_SCACHETYPE_INVALID: - *((u_long *)dptr) = SMB_ATTR_DIRECTORY; + fa->extFileAttributes = SMB_ATTR_DIRECTORY; break; default: /* if we get here we either have a normal file @@ -3917,49 +4044,24 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, * and odd means it is to be treated as a file. */ if (mustFake && (scp->fid.vnode & 0x1)) - *((u_long *)dptr) = SMB_ATTR_DIRECTORY; + fa->extFileAttributes = SMB_ATTR_DIRECTORY; else - *((u_long *)dptr) = SMB_ATTR_NORMAL; + fa->extFileAttributes = SMB_ATTR_NORMAL; } /* merge in hidden attribute */ if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) { - *((u_long *)dptr) |= SMB_ATTR_HIDDEN; + fa->extFileAttributes |= SMB_ATTR_HIDDEN; } - dptr += 4; } else { + smb_V3FileAttrsShort * fa = (smb_V3FileAttrsShort *) patchp->dptr; + /* 1969-12-31 23:59:58 +00*/ dosTime = 0xEBBFBF7D; - /* and copy out date */ - shortTemp = (dosTime>>16) & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* copy out creation time */ - shortTemp = dosTime & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* and copy out date */ - shortTemp = (dosTime>>16) & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* copy out access time */ - shortTemp = dosTime & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* and copy out date */ - shortTemp = (dosTime>>16) & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* copy out mod time */ - shortTemp = dosTime & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 10; + fa->creationDateTime = MAKELONG(HIWORD(dosTime),LOWORD(dosTime)); + fa->lastAccessDateTime = fa->creationDateTime; + fa->lastWriteDateTime = fa->creationDateTime; /* set the attribute */ switch (scp->fileType) { @@ -3967,16 +4069,14 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, case CM_SCACHETYPE_MOUNTPOINT: case CM_SCACHETYPE_SYMLINK: case CM_SCACHETYPE_INVALID: - attr = SMB_ATTR_DIRECTORY; + fa->attributes = SMB_ATTR_DIRECTORY; default: - attr = SMB_ATTR_NORMAL; + fa->attributes = SMB_ATTR_NORMAL; } /* merge in hidden (dot file) attribute */ if ( patchp->flags & SMB_DIRLISTPATCH_DOTFILE ) { - attr |= SMB_ATTR_HIDDEN; + fa->attributes |= SMB_ATTR_HIDDEN; } - *dptr++ = attr & 0xff; - *dptr++ = (attr >> 8) & 0xff; } cm_ReleaseSCache(scp); @@ -4009,33 +4109,20 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, lock_ConvertWToR(&scp->rw); - dptr = patchp->dptr; - if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) { + smb_V3FileAttrsLong * fa = (smb_V3FileAttrsLong *) patchp->dptr; + /* get filetime */ smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime); - /* copy to Creation Time */ - *((FILETIME *)dptr) = ft; - dptr += 8; - - /* copy to Last Access Time */ - *((FILETIME *)dptr) = ft; - dptr += 8; - - /* copy to Last Write Time */ - *((FILETIME *)dptr) = ft; - dptr += 8; - - /* copy to Change Time */ - *((FILETIME *)dptr) = ft; - dptr += 8; + fa->creationTime = ft; + fa->lastAccessTime = ft; + fa->lastWriteTime = ft; + fa->lastChangeTime = ft; /* Use length for both file length and alloc length */ - *((LARGE_INTEGER *)dptr) = scp->length; - dptr += 8; - *((LARGE_INTEGER *)dptr) = scp->length; - dptr += 8; + fa->endOfFile = scp->length; + fa->allocationSize = scp->length; /* Copy attributes */ lattr = smb_ExtAttributes(scp); @@ -4053,49 +4140,23 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, else lattr |= SMB_ATTR_HIDDEN; } - *((u_long *)dptr) = lattr; - dptr += 4; + + fa->extFileAttributes = lattr; } else { + smb_V3FileAttrsShort * fa = (smb_V3FileAttrsShort *) patchp->dptr; + /* get dos time */ smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime); - /* and copy out date */ - shortTemp = (dosTime>>16) & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* copy out creation time */ - shortTemp = dosTime & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* and copy out date */ - shortTemp = (dosTime>>16) & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* copy out access time */ - shortTemp = dosTime & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* and copy out date */ - shortTemp = (dosTime>>16) & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; - - /* copy out mod time */ - shortTemp = dosTime & 0xffff; - *((u_short *)dptr) = shortTemp; - dptr += 2; + fa->creationDateTime = MAKELONG(HIWORD(dosTime), LOWORD(dosTime)); + fa->lastAccessDateTime = fa->creationDateTime; + fa->lastWriteDateTime = fa->creationDateTime; /* copy out file length and alloc length, * using the same for both */ - *((u_long *)dptr) = scp->length.LowPart; - dptr += 4; - *((u_long *)dptr) = scp->length.LowPart; - dptr += 4; + fa->dataSize = scp->length.LowPart; + fa->allocationSize = scp->length.LowPart; /* finally copy out attributes as short */ attr = smb_Attributes(scp); @@ -4106,8 +4167,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,smb_dirListPatch_t **dirPatchespp, else lattr |= SMB_ATTR_HIDDEN; } - *dptr++ = attr & 0xff; - *dptr++ = (attr >> 8) & 0xff; + fa->attributes = attr; } lock_ReleaseRead(&scp->rw); @@ -4267,6 +4327,8 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags) the usual mechanism. This function will return either CM_ERROR_NOSUCHFILE or SUCCESS. + + TRANS2_FIND_FIRST2 and TRANS2_FIND_NEXT2 */ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx) { @@ -4277,16 +4339,16 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op int maxCount; smb_dirListPatch_t *dirListPatchesp; smb_dirListPatch_t *curPatchp; - long orbytes; /* # of bytes in this output record */ - long ohbytes; /* # of bytes, except file name */ - long onbytes; /* # of bytes in name, incl. term. null */ + size_t orbytes; /* # of bytes in this output record */ + size_t ohbytes; /* # of bytes, except file name */ + size_t onbytes; /* # of bytes in name, incl. term. null */ cm_scache_t *scp = NULL; cm_scache_t *targetscp = NULL; cm_user_t *userp = NULL; char *op; /* output data ptr */ char *origOp; /* original value of op */ cm_space_t *spacep; /* for pathname buffer */ - long maxReturnData; /* max # of return data */ + unsigned long maxReturnData; /* max # of return data */ long maxReturnParms; /* max # of return parms */ long bytesInBuffer; /* # data bytes in the output buffer */ char *maskp; /* mask part of path */ @@ -4302,6 +4364,8 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op cm_dirEntry_t * dep = NULL; cm_req_t req; char * s; + void * attrp = NULL; + smb_tran2Find_t * fp; cm_InitReq(&req); @@ -4317,7 +4381,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op maxCount = p->parmsp[1]; infoLevel = p->parmsp[3]; searchFlags = p->parmsp[2]; - pathp = ((char *) p->parmsp) + 12; /* points to path */ + pathp = smb_ParseStringT2Parm(p, (char *) &(p->parmsp[6]), NULL, SMB_STRF_ANSIPATH); nextCookie = 0; maskp = strrchr(pathp, '\\'); if (maskp == NULL) @@ -4333,27 +4397,42 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op switch ( infoLevel ) { case SMB_INFO_STANDARD: s = "InfoStandard"; + ohbytes = sizeof(fp->u.FstandardInfo); break; + case SMB_INFO_QUERY_EA_SIZE: + ohbytes = sizeof(fp->u.FeaSizeInfo); s = "InfoQueryEaSize"; break; + case SMB_INFO_QUERY_EAS_FROM_LIST: + ohbytes = sizeof(fp->u.FeasFromListInfo); s = "InfoQueryEasFromList"; break; + case SMB_FIND_FILE_DIRECTORY_INFO: s = "FindFileDirectoryInfo"; + ohbytes = sizeof(fp->u.FfileDirectoryInfo); break; + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: s = "FindFileFullDirectoryInfo"; + ohbytes = sizeof(fp->u.FfileFullDirectoryInfo); break; + case SMB_FIND_FILE_NAMES_INFO: s = "FindFileNamesInfo"; + ohbytes = sizeof(fp->u.FfileNamesInfo); break; + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: s = "FindFileBothDirectoryInfo"; + ohbytes = sizeof(fp->u.FfileBothDirectoryInfo); break; + default: s = "unknownInfoLevel"; + ohbytes = 0; } osi_Log1(smb_logp, "smb_T2SearchDirSingle info level: %s", s); @@ -4362,7 +4441,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op "smb_T2SearchDirSingle attr 0x%x, info level 0x%x, max count %d, flags 0x%x", attribute, infoLevel, maxCount, searchFlags); - if (infoLevel > SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { + if (ohbytes == 0) { osi_Log1(smb_logp, "Unsupported InfoLevel 0x%x", infoLevel); return CM_ERROR_INVAL; } @@ -4370,6 +4449,9 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) searchFlags &= ~TRAN2_FIND_FLAG_RETURN_RESUME_KEYS; /* no resume keys */ + if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS) + ohbytes += 4; + dirListPatchesp = NULL; maxReturnData = p->maxReturnData; @@ -4478,6 +4560,8 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op op += 4; } + fp = (smb_tran2Find_t *) op; + if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO && targetscp->fid.vnode != 0 && !cm_Is8Dot3(maskp)) { @@ -4520,29 +4604,10 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op } - /* Check if the name will fit */ - if (infoLevel < 0x101) - ohbytes = 23; /* pre-NT */ - else if (infoLevel == SMB_FIND_FILE_NAMES_INFO) - ohbytes = 12; /* NT names only */ - else - ohbytes = 64; /* NT */ - - if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) - ohbytes += 26; /* Short name & length */ - - if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS) { - ohbytes += 4; /* if resume key required */ - } - - if (infoLevel != SMB_INFO_STANDARD - && infoLevel != SMB_FIND_FILE_DIRECTORY_INFO - && infoLevel != SMB_FIND_FILE_NAMES_INFO) - ohbytes += 4; /* EASIZE */ - /* add header to name & term. null */ - onbytes = (int)strlen(maskp); - orbytes = ohbytes + onbytes + 1; + onbytes = 0; + smb_UnparseString(opx, NULL, maskp, &onbytes, SMB_STRF_ANSIPATH); + orbytes = ohbytes + onbytes; /* now, we round up the record to a 4 byte alignment, and we make * sure that we have enough room here for even the aligned version @@ -4570,42 +4635,80 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op * preceded by its length. */ /* First zero everything else */ - memset(origOp, 0, ohbytes); + memset(origOp, 0, orbytes); - if (infoLevel <= SMB_FIND_FILE_DIRECTORY_INFO) - *(origOp + ohbytes - 1) = (unsigned char) onbytes; - else if (infoLevel == SMB_FIND_FILE_NAMES_INFO) - *((u_long *)(op + 8)) = onbytes; - else - *((u_long *)(op + 60)) = onbytes; - strcpy(origOp+ohbytes, maskp); - if (smb_StoreAnsiFilenames) - CharToOem(origOp+ohbytes, origOp+ohbytes); + onbytes = 0; + smb_UnparseString(opx, origOp + ohbytes, maskp, &onbytes, SMB_STRF_ANSIPATH); - /* Short name if requested and needed */ - if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { + switch (infoLevel) { + case SMB_INFO_STANDARD: + fp->u.FstandardInfo.fileNameLength = onbytes; + attrp = &fp->u.FstandardInfo.fileAttrs; + break; + + case SMB_INFO_QUERY_EA_SIZE: + fp->u.FeaSizeInfo.fileNameLength = onbytes; + attrp = &fp->u.FeaSizeInfo.fileAttrs; + fp->u.FeaSizeInfo.eaSize = 0; + break; + + case SMB_INFO_QUERY_EAS_FROM_LIST: + fp->u.FeasFromListInfo.fileNameLength = onbytes; + attrp = &fp->u.FeasFromListInfo.fileAttrs; + fp->u.FeasFromListInfo.eaSize = 0; + break; + + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: if (NeedShortName) { - strcpy(op + 70, shortName); - if (smb_StoreAnsiFilenames) - CharToOem(op + 70, op + 70); - *(op + 68) = (char)(shortNameEnd - shortName); - } - } +#ifdef SMB_UNICODE + int nchars; - /* NextEntryOffset and FileIndex */ - if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) { - int entryOffset = orbytes + align; - *((u_long *)op) = 0; - *((u_long *)(op+4)) = 0; + nchars = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, + shortName, -1, + fp->u.FfileBothDirectoryInfo.shortName, + sizeof(fp->u.FfileBothDirectoryInfo.shortName) / sizeof(wchar_t)); + if (nchars > 0) + fp->u.FfileBothDirectoryInfo.shortNameLength = (nchars - 1)*sizeof(wchar_t); + else + fp->u.FfileBothDirectoryInfo.shortNameLength = 0; + fp->u.FfileBothDirectoryInfo.reserved = 0; +#else + strcpy(fp->u.FfileBothDirectoryInfo.shortName, + shortName); + fp->u.FfileBothDirectoryInfo.shortNameLength = strlen(shortName); +#endif + } + /* Fallthrough */ + + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + fp->u.FfileFullDirectoryInfo.eaSize = 0; + /* Fallthrough */ + + case SMB_FIND_FILE_DIRECTORY_INFO: + fp->u.FfileDirectoryInfo.nextEntryOffset = 0; + fp->u.FfileDirectoryInfo.fileIndex = 0; + attrp = &fp->u.FfileDirectoryInfo.fileAttrs; + fp->u.FfileDirectoryInfo.fileNameLength = onbytes; + break; + + case SMB_FIND_FILE_NAMES_INFO: + fp->u.FfileNamesInfo.nextEntryOffset = 0; + fp->u.FfileNamesInfo.fileIndex = 0; + fp->u.FfileNamesInfo.fileNameLength = onbytes; + break; + + default: + /* we shouldn't hit this case */ + osi_assertx(FALSE, "Unknown query type"); } if (infoLevel != SMB_FIND_FILE_NAMES_INFO) { + osi_assert(attrp != NULL); + curPatchp = malloc(sizeof(*curPatchp)); osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q); - curPatchp->dptr = op; - if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) - curPatchp->dptr += 8; + curPatchp->dptr = attrp; if (smb_hideDotFiles && smb_IsDotFile(maskp)) { curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE; @@ -4674,6 +4777,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op } +/* TRANS2_FIND_FIRST2 and TRANS2_FIND_NEXT2 */ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx) { int attribute; @@ -4687,9 +4791,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t smb_dirListPatch_t *curPatchp = 0; cm_buf_t *bufferp; long temp; - long orbytes; /* # of bytes in this output record */ - long ohbytes; /* # of bytes, except file name */ - long onbytes; /* # of bytes in name, incl. term. null */ + size_t orbytes; /* # of bytes in this output record */ + size_t ohbytes; /* # of bytes, except file name */ + size_t onbytes; /* # of bytes in name, incl. term. null */ osi_hyper_t dirLength; osi_hyper_t bufferOffset; osi_hyper_t curOffset; @@ -4707,8 +4811,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t char *op; /* output data ptr */ char *origOp; /* original value of op */ cm_space_t *spacep; /* for pathname buffer */ - long maxReturnData; /* max # of return data */ - long maxReturnParms; /* max # of return parms */ + unsigned long maxReturnData; /* max # of return data */ + unsigned long maxReturnParms; /* max # of return parms */ long bytesInBuffer; /* # data bytes in the output buffer */ int starPattern; char *maskp; /* mask part of path */ @@ -4717,7 +4821,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t int eos; smb_tran2Packet_t *outp; /* response packet */ char *tidPathp; - int align; + unsigned int align; char shortName[13]; /* 8.3 name if needed */ int NeedShortName; int foundInexact; @@ -4725,7 +4829,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t int fileType; cm_fid_t fid; cm_req_t req; + void * attrp; char * s; + smb_tran2Find_t * fp; cm_InitReq(&req); @@ -4736,9 +4842,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t maxCount = p->parmsp[1]; infoLevel = p->parmsp[3]; searchFlags = p->parmsp[2]; - pathp = ((char *) p->parmsp) + 12; /* points to path */ - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[6]), NULL, SMB_STRF_ANSIPATH); nextCookie = 0; maskp = strrchr(pathp, '\\'); if (maskp == NULL) @@ -4766,7 +4870,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return code; } } -#endif +#endif /* NOFINDFIRSTOPTIMIZE */ dir_enums++; dsp = smb_NewDirSearch(1); @@ -4795,27 +4899,42 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t switch ( infoLevel ) { case SMB_INFO_STANDARD: s = "InfoStandard"; + ohbytes = sizeof(fp->u.FstandardInfo); break; + case SMB_INFO_QUERY_EA_SIZE: + ohbytes = sizeof(fp->u.FeaSizeInfo); s = "InfoQueryEaSize"; break; + case SMB_INFO_QUERY_EAS_FROM_LIST: + ohbytes = sizeof(fp->u.FeasFromListInfo); s = "InfoQueryEasFromList"; break; + case SMB_FIND_FILE_DIRECTORY_INFO: s = "FindFileDirectoryInfo"; + ohbytes = sizeof(fp->u.FfileDirectoryInfo); break; + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: s = "FindFileFullDirectoryInfo"; + ohbytes = sizeof(fp->u.FfileFullDirectoryInfo); break; + case SMB_FIND_FILE_NAMES_INFO: s = "FindFileNamesInfo"; + ohbytes = sizeof(fp->u.FfileNamesInfo); break; + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: s = "FindFileBothDirectoryInfo"; + ohbytes = sizeof(fp->u.FfileBothDirectoryInfo); break; + default: s = "unknownInfoLevel"; + ohbytes = 0; } osi_Log1(smb_logp, "T2 search dir info level: %s", s); @@ -4827,7 +4946,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t osi_Log3(smb_logp, "...T2 search op %d, id %d, nextCookie 0x%x", p->opcode, dsp->cookie, nextCookie); - if (infoLevel > SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { + if (ohbytes == 0) { osi_Log1(smb_logp, "Unsupported InfoLevel 0x%x", infoLevel); smb_ReleaseDirSearch(dsp); return CM_ERROR_INVAL; @@ -4836,6 +4955,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) searchFlags &= ~TRAN2_FIND_FLAG_RETURN_RESUME_KEYS; /* no resume keys */ + if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS) + ohbytes += 4; + dirListPatchesp = NULL; maxReturnData = p->maxReturnData; @@ -4981,6 +5103,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t /* skip over resume key */ op += 4; + fp = (smb_tran2Find_t *) op; + /* make sure that curOffset.LowPart doesn't point to the first * 32 bytes in the 2nd through last dir page, and that it doesn't * point at the first 13 32-byte chunks in the first dir page, @@ -5189,29 +5313,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t } /* finally check if this name will fit */ - - /* standard dir entry stuff */ - if (infoLevel < 0x101) - ohbytes = 23; /* pre-NT */ - else if (infoLevel == SMB_FIND_FILE_NAMES_INFO) - ohbytes = 12; /* NT names only */ - else - ohbytes = 64; /* NT */ - - if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) - ohbytes += 26; /* Short name & length */ - - if (searchFlags & TRAN2_FIND_FLAG_RETURN_RESUME_KEYS) { - ohbytes += 4; /* if resume key required */ - } - - if ( infoLevel != SMB_INFO_STANDARD && - infoLevel != SMB_FIND_FILE_DIRECTORY_INFO && - infoLevel != SMB_FIND_FILE_NAMES_INFO) - ohbytes += 4; /* EASIZE */ - - /* add header to name & term. null */ - orbytes = onbytes + ohbytes + 1; + onbytes = 0; + smb_UnparseString(opx, NULL, dep->name, &onbytes, SMB_STRF_ANSIPATH); + orbytes = ohbytes + onbytes; /* now, we round up the record to a 4 byte alignment, * and we make sure that we have enough room here for @@ -5223,6 +5327,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t align = (4 - (orbytes & 3)) & 3; else align = 0; + if (orbytes + bytesInBuffer + align > maxReturnData) { osi_Log1(smb_logp, "T2 dir search exceed max return data %d", maxReturnData); @@ -5234,38 +5339,77 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t * Put out the name, preceded by its length. */ /* First zero everything else */ - memset(origOp, 0, ohbytes); + memset(origOp, 0, orbytes); - if (infoLevel <= SMB_FIND_FILE_DIRECTORY_INFO) - *(origOp + ohbytes - 1) = (unsigned char) onbytes; - else if (infoLevel == SMB_FIND_FILE_NAMES_INFO) - *((u_long *)(op + 8)) = onbytes; - else - *((u_long *)(op + 60)) = onbytes; - strcpy(origOp+ohbytes, dep->name); - if (smb_StoreAnsiFilenames) - CharToOem(origOp+ohbytes, origOp+ohbytes); + onbytes = 0; + smb_UnparseString(opx, origOp + ohbytes, dep->name, &onbytes, SMB_STRF_ANSIPATH); - /* Short name if requested and needed */ - if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { + switch (infoLevel) { + case SMB_INFO_STANDARD: + fp->u.FstandardInfo.fileNameLength = onbytes; + attrp = &fp->u.FstandardInfo.fileAttrs; + break; + + case SMB_INFO_QUERY_EA_SIZE: + fp->u.FeaSizeInfo.fileNameLength = onbytes; + attrp = &fp->u.FeaSizeInfo.fileAttrs; + fp->u.FeaSizeInfo.eaSize = 0; + break; + + case SMB_INFO_QUERY_EAS_FROM_LIST: + fp->u.FeasFromListInfo.fileNameLength = onbytes; + attrp = &fp->u.FeasFromListInfo.fileAttrs; + fp->u.FeasFromListInfo.eaSize = 0; + break; + + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: if (NeedShortName) { - strcpy(op + 70, shortName); - if (smb_StoreAnsiFilenames) - CharToOem(op + 70, op + 70); - *(op + 68) = (char)(shortNameEnd - shortName); +#ifdef SMB_UNICODE + int nchars; + + nchars = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, + shortName, -1, + fp->u.FfileBothDirectoryInfo.shortName, + sizeof(fp->u.FfileBothDirectoryInfo.shortName) / sizeof(wchar_t)); + if (nchars > 0) + fp->u.FfileBothDirectoryInfo.shortNameLength = (nchars - 1)*sizeof(wchar_t); + else + fp->u.FfileBothDirectoryInfo.shortNameLength = 0; + fp->u.FfileBothDirectoryInfo.reserved = 0; +#else + strcpy(fp->u.FfileBothDirectoryInfo.shortName, + shortName); + fp->u.FfileBothDirectoryInfo.shortNameLength = strlen(shortName); +#endif } + /* Fallthrough */ + + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: + fp->u.FfileFullDirectoryInfo.eaSize = 0; + /* Fallthrough */ + + case SMB_FIND_FILE_DIRECTORY_INFO: + fp->u.FfileDirectoryInfo.nextEntryOffset = orbytes + align; + fp->u.FfileDirectoryInfo.fileIndex = nextEntryCookie; + attrp = &fp->u.FfileDirectoryInfo.fileAttrs; + fp->u.FfileDirectoryInfo.fileNameLength = onbytes; + break; + + case SMB_FIND_FILE_NAMES_INFO: + fp->u.FfileNamesInfo.nextEntryOffset = orbytes + align; + fp->u.FfileNamesInfo.fileIndex = nextEntryCookie; + fp->u.FfileNamesInfo.fileNameLength = onbytes; + attrp = NULL; + break; + + default: + /* we shouldn't hit this case */ + osi_assertx(FALSE, "Unknown query type"); } /* now, adjust the # of entries copied */ returnedNames++; - /* NextEntryOffset and FileIndex */ - if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) { - int entryOffset = orbytes + align; - *((u_long *)op) = entryOffset; - *((u_long *)(op+4)) = nextEntryCookie; - } - /* now we emit the attribute. This is tricky, since * we need to really stat the file to find out what * type of entry we've got. Right now, we're copying @@ -5280,17 +5424,16 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t * safe to unlock the directory. */ if (infoLevel != SMB_FIND_FILE_NAMES_INFO) { + osi_assert(attrp != NULL); curPatchp = malloc(sizeof(*curPatchp)); osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q); - curPatchp->dptr = op; - if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) - curPatchp->dptr += 8; + curPatchp->dptr = attrp; if (smb_hideDotFiles && smb_IsDotFile(dep->name)) { curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE; - } - else + } else { curPatchp->flags = 0; + } cm_SetFid(&curPatchp->fid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique)); @@ -5307,7 +5450,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t bytesInBuffer += orbytes; /* and pad the record out */ - while (--align >= 0) { + while (align-- > 0) { *origOp++ = 0; bytesInBuffer++; } @@ -5408,6 +5551,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return 0; } +/* SMB_COM_FIND_CLOSE2 */ long smb_ReceiveV3FindClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { int dirHandle; @@ -5432,12 +5576,15 @@ long smb_ReceiveV3FindClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp return 0; } + +/* SMB_COM_FIND_NOTIFY_CLOSE */ long smb_ReceiveV3FindNotifyClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_SetSMBDataLength(outp, 0); return 0; } +/* SMB_COM_OPEN_ANDX */ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *pathp; @@ -5452,7 +5599,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) smb_fid_t *fidp; int attributes; char *lastNamep; - afs_uint32 dosTime; + unsigned long dosTime; int openFun; int trunc; int openMode; @@ -5482,9 +5629,8 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if (attributes & SMB_ATTR_READONLY) initialModeBits &= ~0222; - pathp = smb_GetSMBData(inp, NULL); - if (smb_StoreAnsiFilenames) - OemToChar(pathp,pathp); + pathp = smb_ParseASCIIBlock(inp, smb_GetSMBData(inp, NULL), NULL, + SMB_STRF_ANSIPATH); spacep = inp->spacep; smb_StripLastComponent(spacep->data, &lastNamep, pathp); @@ -5785,6 +5931,7 @@ static void smb_GetLockParams(unsigned char LockType, } } +/* SMB_COM_LOCKING_ANDX */ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { cm_req_t req; @@ -6079,6 +6226,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return code; } +/* SMB_COM_QUERY_INFORMATION2 */ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned short fid; @@ -6166,6 +6314,7 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * return code; } +/* SMB_COM_SET_INFORMATION2 */ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned short fid; @@ -6235,6 +6384,7 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * return code; } +/* SMB_COM_WRITE_ANDX */ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { osi_hyper_t offset; @@ -6369,6 +6519,7 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return code; } +/* SMB_COM_READ_ANDX */ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { osi_hyper_t offset; @@ -6523,6 +6674,7 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) #define FILE_DELETE_ON_CLOSE 0x1000 #define FILE_OPEN_BY_FILE_ID 0x2000 +/* SMB_COM_NT_CREATE_ANDX */ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *pathp, *realPathp; @@ -6619,13 +6771,16 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if (extAttributes & SMB_ATTR_READONLY) initialModeBits &= ~0222; - pathp = smb_GetSMBData(inp, NULL); + if (nameLength == 0) + return CM_ERROR_INVAL; + + pathp = smb_ParseStringCb(inp, smb_GetSMBData(inp, NULL), nameLength, + NULL, SMB_STRF_ANSIPATH); + /* Sometimes path is not null-terminated, so we make a copy. */ realPathp = malloc(nameLength+1); memcpy(realPathp, pathp, nameLength); realPathp[nameLength] = 0; - if (smb_StoreAnsiFilenames) - OemToChar(realPathp,realPathp); spacep = inp->spacep; smb_StripLastComponent(spacep->data, &lastNamep, realPathp); @@ -7357,6 +7512,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) * A lot of stuff copied verbatim from NT Create&X to NT Tran Create. * Instead, ultimately, would like to use a subroutine for common code. */ + +/* NT_TRANSACT_CREATE (SMB_COM_NT_TRANSACT) */ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { char *pathp, *realPathp; @@ -7466,13 +7623,11 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out initialModeBits &= ~0222; pathp = parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR); + pathp = smb_ParseStringCch(inp, pathp, nameLength, NULL, SMB_STRF_ANSIPATH); /* Sometimes path is not null-terminated, so we make a copy. */ realPathp = malloc(nameLength+1); memcpy(realPathp, pathp, nameLength); realPathp[nameLength] = 0; - if (smb_StoreAnsiFilenames) - OemToChar(realPathp,realPathp); - spacep = cm_GetSpace(); smb_StripLastComponent(spacep->data, &lastNamep, realPathp); @@ -8095,6 +8250,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out return 0; } +/* NT_TRANSACT_NOTIFY_CHANGE (SMB_COM_NT_TRANSACT) */ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { @@ -8193,6 +8349,7 @@ unsigned char nullSecurityDesc[36] = { /* "null SID" group SID */ }; +/* NT_TRANSACT_QUERY_SECURITY_DESC (SMB_COM_NT_TRANSACT) */ long smb_ReceiveNTTranQuerySecurityDesc(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { int parmOffset, parmCount, dataOffset, dataCount; @@ -8261,6 +8418,10 @@ long smb_ReceiveNTTranQuerySecurityDesc(smb_vc_t *vcp, smb_packet_t *inp, smb_pa return CM_ERROR_BUFFERTOOSMALL; } +/* SMB_COM_NT_TRANSACT + + SMB_COM_NT_TRANSACT_SECONDARY should also be handled here. + */ long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned short function; @@ -8274,20 +8435,20 @@ long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) ((smb_t *)outp)->flg2 |= SMB_FLAGS2_IS_LONG_NAME; switch (function) { - case 1: + case 1: /* NT_TRANSACT_CREATE */ return smb_ReceiveNTTranCreate(vcp, inp, outp); - case 2: + case 2: /* NT_TRANSACT_IOCTL */ osi_Log0(smb_logp, "SMB NT Transact Ioctl - not implemented"); break; - case 3: + case 3: /* NT_TRANSACT_SET_SECURITY_DESC */ osi_Log0(smb_logp, "SMB NT Transact SetSecurityDesc - not implemented"); break; - case 4: + case 4: /* NT_TRANSACT_NOTIFY_CHANGE */ return smb_ReceiveNTTranNotifyChange(vcp, inp, outp); - case 5: + case 5: /* NT_TRANSACT_RENAME */ osi_Log0(smb_logp, "SMB NT Transact Rename - not implemented"); break; - case 6: + case 6: /* NT_TRANSACT_QUERY_SECURITY_DESC */ return smb_ReceiveNTTranQuerySecurityDesc(vcp, inp, outp); case 7: osi_Log0(smb_logp, "SMB NT Transact Query Quota - not implemented"); @@ -8530,6 +8691,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter, lock_ReleaseMutex(&smb_Dir_Watch_Lock); } +/* SMB_COM_NT_CANCEL */ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { unsigned char *replyWctp; @@ -8628,12 +8790,8 @@ long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) } tp = smb_GetSMBData(inp, NULL); - oldPathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(oldPathp,oldPathp); - newPathp = smb_ParseASCIIBlock(tp, &tp); - if (smb_StoreAnsiFilenames) - OemToChar(newPathp,newPathp); + oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, 0); + newPathp = smb_ParseASCIIBlock(inp, tp, &tp, 0); osi_Log3(smb_logp, "NTRename for [%s]->[%s] type [%s]", osi_LogSaveString(smb_logp, oldPathp), diff --git a/src/WINNT/afsd/smb3.h b/src/WINNT/afsd/smb3.h index 2ab214af41..99209dfb16 100644 --- a/src/WINNT/afsd/smb3.h +++ b/src/WINNT/afsd/smb3.h @@ -30,10 +30,12 @@ typedef struct smb_tran2Packet { unsigned short res[6]; /* contains PidHigh */ unsigned short *parmsp; /* parms */ unsigned char *datap; /* data bytes */ + cm_space_t * stringsp; /* decoded strings */ } smb_tran2Packet_t; /* for flags field */ #define SMB_TRAN2PFLAG_ALLOC 1 +#define SMB_TRAN2PFLAG_USEUNICODE 2 typedef struct smb_tran2Dispatch { long (*procp)(smb_vc_t *, smb_tran2Packet_t *, smb_packet_t *); @@ -56,14 +58,14 @@ typedef struct smb_tran2QFSInfo { struct { unsigned long vsn; /* volume serial number */ char vnCount; /* count of chars in label, incl null */ - char label[12]; /* pad out with nulls */ + char /* STRING */ label[24]; /* pad out with nulls */ } volumeInfo; struct { FILETIME vct; /* volume creation time */ unsigned long vsn; /* volume serial number */ unsigned long vnCount; /* length of volume label in bytes */ char res[2]; /* reserved */ - char label[10]; /* volume label */ + char /* STRING */ label[20]; /* volume label */ } FSvolumeInfo; struct { LARGE_INTEGER totalAllocUnits; /* on the disk */ @@ -79,7 +81,7 @@ typedef struct smb_tran2QFSInfo { unsigned long attributes; unsigned long maxCompLength; /* max path component length */ unsigned long FSnameLength; /* length of file system name */ - unsigned char FSname[12]; + unsigned char /* STRING */ FSname[24]; /* File system name */ } FSattributeInfo; } u; } smb_tran2QFSInfo_t; @@ -137,7 +139,7 @@ typedef struct { } QPfileEaInfo; struct { unsigned long fileNameLength; - unsigned char fileName[512]; + unsigned char fileName[512]; /* STRING */ } QPfileNameInfo; struct { FILETIME creationTime; @@ -158,18 +160,18 @@ typedef struct { unsigned long mode; unsigned long alignmentRequirement; unsigned long fileNameLength; - unsigned char fileName[512]; + unsigned char fileName[512]; /* STRING */ } QPfileAllInfo; struct { unsigned long fileNameLength; - unsigned char fileName[512]; + unsigned char fileName[512]; /* STRING */ } QPfileAltNameInfo; struct { unsigned long nextEntryOffset; unsigned long streamNameLength; LARGE_INTEGER streamSize; LARGE_INTEGER streamAllocationSize; - unsigned char fileName[512]; + unsigned char fileName[512]; /* STRING */ } QPfileStreamInfo; struct { LARGE_INTEGER compressedFileSize; @@ -207,6 +209,79 @@ typedef struct { } QFfileNameInfo; } u; } smb_tran2QFileInfo_t; + +typedef struct { + unsigned long creationDateTime; /* SMB_DATE / SMB_TIME */ + unsigned long lastAccessDateTime; /* SMB_DATE / SMB_TIME */ + unsigned long lastWriteDateTime; /* SMB_DATE / SMB_TIME */ + unsigned long dataSize; + unsigned long allocationSize; + unsigned short attributes; +} smb_V3FileAttrsShort; + +typedef struct { + FILETIME creationTime; + FILETIME lastAccessTime; + FILETIME lastWriteTime; + FILETIME lastChangeTime; + LARGE_INTEGER endOfFile; + LARGE_INTEGER allocationSize; + unsigned long extFileAttributes; +} smb_V3FileAttrsLong; + +typedef struct { + union { + struct { + smb_V3FileAttrsShort fileAttrs; + unsigned char fileNameLength; + /* STRING fileName */ + } FstandardInfo; + + struct { + smb_V3FileAttrsShort fileAttrs; + unsigned long eaSize; + unsigned char fileNameLength; + /* STRING fileName */ + } FeaSizeInfo, FeasFromListInfo; + + struct { + unsigned long nextEntryOffset; + unsigned long fileIndex; + smb_V3FileAttrsLong fileAttrs; + unsigned long fileNameLength; + /* STRING fileName */ + } FfileDirectoryInfo; + + struct { + unsigned long nextEntryOffset; + unsigned long fileIndex; + smb_V3FileAttrsLong fileAttrs; + unsigned long fileNameLength; + unsigned long eaSize; + /* STRING fileName */ + } FfileFullDirectoryInfo; + + struct { + unsigned long nextEntryOffset; + unsigned long fileIndex; + smb_V3FileAttrsLong fileAttrs; + unsigned long fileNameLength; + unsigned long eaSize; + unsigned char shortNameLength; + unsigned char reserved; + wchar_t shortName[12]; + /* STRING fileName */ + } FfileBothDirectoryInfo; + + struct { + unsigned long nextEntryOffset; + unsigned long fileIndex; + unsigned long fileNameLength; + /* STRING fileName */ + } FfileNamesInfo; + } u; +} smb_tran2Find_t; + #pragma pack(pop) /* more than enough opcodes for today, anyway */ diff --git a/src/WINNT/afsd/smb_iocons.h b/src/WINNT/afsd/smb_iocons.h index bf23849e43..8f73dac0ee 100644 --- a/src/WINNT/afsd/smb_iocons.h +++ b/src/WINNT/afsd/smb_iocons.h @@ -94,6 +94,7 @@ struct sbstruct { #define VIOC_UUIDCTL 0x30 #define VIOC_PATH_AVAILABILITY 0x31 #define VIOC_GETFILETYPE 0x32 +#define VIOC_UNICODECTL 0x33 #define VIOC_VOLSTAT_TEST 0x3F /* Not to exceed SMB_IOCTL_MAXPROCS from smb_ioctl.h */ diff --git a/src/WINNT/afsd/smb_ioctl.c b/src/WINNT/afsd/smb_ioctl.c index 7f3715eaa7..76a9d251dc 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -82,6 +82,7 @@ void smb_InitIoctl(void) smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = cm_IoctlPathAvailability; smb_ioctlProcsp[VIOC_GETFILETYPE] = cm_IoctlGetFileType; smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = cm_IoctlVolStatTest; + smb_ioctlProcsp[VIOC_UNICODECTL] = cm_IoctlUnicodeControl; } /* called to make a fid structure into an IOCTL fid structure */ diff --git a/src/WINNT/afsd/symlink.c b/src/WINNT/afsd/symlink.c index 72da4c0674..d9de596e48 100644 --- a/src/WINNT/afsd/symlink.c +++ b/src/WINNT/afsd/symlink.c @@ -68,7 +68,7 @@ static int InAFS(register char *apath) blob.out_size = MAXSIZE; blob.out = space; - code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1); if (code) { if ((errno == EINVAL) || (errno == ENOENT)) return 0; @@ -86,7 +86,7 @@ IsFreelanceRoot(char *apath) blob.out_size = MAXSIZE; blob.out = space; - code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1); if (code == 0) return !stricmp("Freelance.Local.Root",space); return 1; /* assume it is because it is more restrictive that way */ @@ -399,7 +399,7 @@ static ListLinkCmd(register struct cmd_syndesc *as, void *arock) blob.out = space; memset(space, 0, MAXSIZE); - code = pioctl(parent_dir, VIOC_LISTSYMLINK, &blob, 1); + code = pioctl_utf8(parent_dir, VIOC_LISTSYMLINK, &blob, 1); if (code == 0) printf("'%s' is a %ssymlink to '%s'\n", @@ -460,6 +460,8 @@ static MakeLinkCmd(register struct cmd_syndesc *as, void *arock) return 1; } + fprintf(stderr, "Creating symlink [%s] to [%s]\n", path, as->parms[1].items->data); + /* create symlink with a special pioctl for Windows NT, since it doesn't * have a symlink system call. */ @@ -467,7 +469,7 @@ static MakeLinkCmd(register struct cmd_syndesc *as, void *arock) blob.in_size = 1 + (long)strlen(as->parms[1].items->data); blob.in = as->parms[1].items->data; blob.out = NULL; - code = pioctl(path, VIOC_SYMLINK, &blob, 0); + code = pioctl_utf8(path, VIOC_SYMLINK, &blob, 0); #else /* not WIN32 */ code = symlink(as->parms[1].items->data, path); #endif /* not WIN32 */ @@ -528,7 +530,7 @@ static RemoveLinkCmd(register struct cmd_syndesc *as, void *arock) blob.in_size = (int)strlen(tp)+1; blob.out = lsbuffer; blob.out_size = sizeof(lsbuffer); - code = pioctl(tbuffer, VIOC_LISTSYMLINK, &blob, 0); + code = pioctl_utf8(tbuffer, VIOC_LISTSYMLINK, &blob, 0); if (code) { if (errno == EINVAL) fprintf(stderr,"symlink: '%s' is not a symlink.\n", ti->data); @@ -547,7 +549,7 @@ static RemoveLinkCmd(register struct cmd_syndesc *as, void *arock) blob.out_size = 0; blob.in = tp; blob.in_size = (long)strlen(tp)+1; - code = pioctl(tbuffer, VIOC_DELSYMLINK, &blob, 0); + code = pioctl_utf8(tbuffer, VIOC_DELSYMLINK, &blob, 0); if (code) { Die(errno, ti->data); } @@ -555,14 +557,58 @@ static RemoveLinkCmd(register struct cmd_syndesc *as, void *arock) return code; } +static void +FreeUtf8CmdLine(int argc, char ** argv) +{ + int i; + for (i=0; i < argc; i++) { + if (argv[i]) + free(argv[i]); + } + free(argv); +} + +static char ** +MakeUtf8Cmdline(int argc, const wchar_t **wargv) +{ + char ** argv; + int i; + + argv = calloc(argc, sizeof(argv[0])); + if (argv == NULL) + return NULL; + + for (i=0; i < argc; i++) { + int s; + + s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, FALSE); + if (s == 0 || + (argv[i] = calloc(s+1, sizeof(char))) == NULL) { + break; + } + + s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], s+1, NULL, FALSE); + if (s == 0) { + break; + } + } + + if (i < argc) { + FreeUtf8CmdLine(argc, argv); + return NULL; + } + + return argv; +} + static struct ViceIoctl gblob; static int debug = 0; -main(argc, argv) -int argc; -char **argv; { +int wmain(int argc, wchar_t **wargv) +{ register afs_int32 code; register struct cmd_syndesc *ts; + char ** argv; #ifdef AFS_AIX32_ENV /* @@ -586,6 +632,7 @@ char **argv; { /* try to find volume location information */ + argv = MakeUtf8Cmdline(argc, wargv); osi_Init(); @@ -606,6 +653,8 @@ char **argv; { if (rxInitDone) rx_Finalize(); #endif /* not WIN32 */ + FreeUtf8CmdLine(argc, argv); + return code; } diff --git a/src/WINNT/client_exp/afs_shl_ext.cpp b/src/WINNT/client_exp/afs_shl_ext.cpp index a9edeb910e..a6bed8e049 100644 --- a/src/WINNT/client_exp/afs_shl_ext.cpp +++ b/src/WINNT/client_exp/afs_shl_ext.cpp @@ -24,6 +24,9 @@ extern "C" { extern "C" { #include "WINNT\afsreg.h" } +#define STRSAFE_NO_DEPRECATE +#include + #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE @@ -75,8 +78,10 @@ HINSTANCE g_hInstance; BOOL CAfsShlExt::InitInstance() { + extern EXPORTED HINSTANCE TaLocale_LoadCorrespondingModuleByName (HINSTANCE hInstance, LPSTR pszFilename, WORD wSearchPriority = MODULE_PRIORITY_BOOSTED); + // Load our translated resources - TaLocale_LoadCorrespondingModuleByName (m_hInstance, TEXT("afs_shl_ext.dll")); + TaLocale_LoadCorrespondingModuleByName (m_hInstance, "afs_shl_ext.dll"); // Register all OLE server (factories) as running. This enables the // OLE libraries to create objects from other applications. @@ -115,8 +120,12 @@ STDAPI DllCanUnloadNow(void) int WideCharToLocal(LPTSTR pLocal, LPCWSTR pWide, DWORD dwChars) { +#ifdef UNICODE + StringCchCopy(pLocal, dwChars, pWide); +#else *pLocal = 0; WideCharToMultiByte( CP_ACP, 0, pWide, -1, pLocal, dwChars, NULL, NULL); +#endif return lstrlen(pLocal); } @@ -155,14 +164,12 @@ STDAPI DllRegisterServer(void) StringFromIID(IID_IShellExt, &pwsz); if(pwsz) { +#ifdef UNICODE + StringCbCopy(szCLSID, sizeof(szCLSID), pwsz); +#else WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL); - LPMALLOC pMalloc; - CoGetMalloc(1, &pMalloc); - if(pMalloc) - { - (pMalloc->Free)(pwsz); - (pMalloc->Release)(); - } +#endif + CoTaskMemFree(pwsz); } else { return E_FAIL; } @@ -172,14 +179,15 @@ STDAPI DllRegisterServer(void) @="Y:\\DEST\\root.client\\usr\\vice\\etc\\afs_shl_ext.dll" "ThreadingModel"="Apartment" */ - HMODULE hModule=GetModuleHandle("afs_shl_ext.dll"); + HMODULE hModule=GetModuleHandle(TEXT("afs_shl_ext.dll")); DWORD z=GetModuleFileName(hModule,szModule,sizeof(szModule)); wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID); if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szModule))!=NOERROR) return lResult; wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID); - if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,"Apartment","ThreadingModel"))!=NOERROR) + if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey, + TEXT("Apartment"),TEXT("ThreadingModel")))!=NOERROR) return lResult; /* @@ -206,7 +214,7 @@ STDAPI DllRegisterServer(void) if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId) { wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved")); - if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,STR_EXT_TITLE,szCLSID))!=NOERROR) + if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,_TEXT(STR_EXT_TITLE),szCLSID))!=NOERROR) return lResult; } wsprintf(szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE); @@ -276,7 +284,7 @@ STDAPI DllRegisterServer(void) TCHAR szData[MAX_PATH]; //Create the value string. - lstrcpy(szData, STR_EXT_TITLE); + lstrcpy(szData, _TEXT(STR_EXT_TITLE)); lResult = RegSetValueEx( hKey, szCLSID, @@ -325,14 +333,12 @@ STDAPI DllUnregisterServer(void) StringFromIID(IID_IShellExt, &pwsz); if(pwsz) { +#ifdef UNICODE + StringCbCopy(szCLSID, sizeof(szCLSID), pwsz); +#else WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL); - LPMALLOC pMalloc; - CoGetMalloc(1, &pMalloc); - if(pMalloc) - { - (pMalloc->Free)(pwsz); - (pMalloc->Release)(); - } +#endif + CoTaskMemFree(pwsz); } else { return E_FAIL; } diff --git a/src/WINNT/client_exp/copy_acl_dlg.cpp b/src/WINNT/client_exp/copy_acl_dlg.cpp index 04439c8677..f334cd89ca 100644 --- a/src/WINNT/client_exp/copy_acl_dlg.cpp +++ b/src/WINNT/client_exp/copy_acl_dlg.cpp @@ -8,6 +8,7 @@ */ #include "stdafx.h" +#include #include #include @@ -72,7 +73,7 @@ void CCopyAclDlg::OnOK() m_bClear = m_Clear.GetCheck() == 1; m_ToDir.GetWindowText(m_strToDir); - if (access(m_strToDir, 0) == -1) { + if (PathIsDirectory(m_strToDir) == -1) { ShowMessageBox(IDS_DIR_DOES_NOT_EXIST_ERROR, MB_ICONEXCLAMATION, IDS_DIR_DOES_NOT_EXIST_ERROR, m_strToDir); return; } @@ -100,7 +101,7 @@ void CCopyAclDlg::OnChangeToDir() void CCopyAclDlg::OnBrowse() { - CFileDialog dlg(TRUE, 0, "*.*", OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY, 0, 0); + CFileDialog dlg(TRUE, 0, TEXT("*.*"), OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY, 0, 0); if (dlg.DoModal() == IDCANCEL) return; diff --git a/src/WINNT/client_exp/gui2fs.cpp b/src/WINNT/client_exp/gui2fs.cpp index 9c1d3b7e9e..13950a18cf 100644 --- a/src/WINNT/client_exp/gui2fs.cpp +++ b/src/WINNT/client_exp/gui2fs.cpp @@ -41,6 +41,9 @@ extern "C" { #include } +#define STRSAFE_NO_DEPRECATE +#include + #define PCCHAR(str) ((char *)(const char *)(str)) #define VL_NOENT (363524L) @@ -68,6 +71,83 @@ static char pn[] = "fs"; static char *szLogFileName = "afsguilog.txt"; #endif +#ifdef UNICODE +class CStringUtf8 : public CStringA +{ +public: + CStringUtf8(const CStringW& csw) : CStringA() + { + SetString(csw); + } + + CStringUtf8(const char * cp) : CStringA(cp) {} + + CStringUtf8() :CStringA() {} + + void SetString(const CStringW& csw) + { + char buffer[1024]; + int rv; + + rv = WideCharToMultiByte(CP_UTF8, 0, csw, -1, + buffer, sizeof(buffer), + NULL, FALSE); + + if (rv != 0) { + CStringA::SetString(buffer); + } else { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + int cb_req; + + cb_req = WideCharToMultiByte(CP_UTF8, 0, csw, -1, NULL, 0, NULL, FALSE); + if (cb_req != 0) { + cb_req ++; + + WideCharToMultiByte(CP_UTF8, 0, csw, -1, CStringA::GetBuffer(cb_req), cb_req, NULL, FALSE); + CStringA::ReleaseBuffer(); + } + } else { +#ifdef DEBUG + DebugBreak(); +#endif + } + } + } + + static CString _Utf8ToCString(const char * ustr) + { + CString cs; + int cch; + + cch = MultiByteToWideChar(CP_UTF8, 0, ustr, -1, NULL, 0); + if (cch == 0) { + cs.Empty(); + return cs; + } + + cch++; + cch = MultiByteToWideChar(CP_UTF8, 0, ustr, -1, cs.GetBuffer(cch), cch); + cs.ReleaseBuffer(); + + return cs; + } +}; + +long pioctl_T(const CString& path, long opcode, struct ViceIoctl * blob, int follow) +{ + CStringUtf8 upath(path); + + return pioctl_utf8(PCCHAR(upath), opcode, blob, follow); +} + +#define Utf8ToCString(cs) CStringUtf8::_Utf8ToCString(cs) +#else +#define pioctl_T(path, op, vblob, follow) pioctl(PCCHAR(path), op, vblob, follow) +#define Utf8ToCString(cs) (cs) +#endif + + + static int VLDBInit(int noAuthFlag, struct afsconf_cell *info) { @@ -82,14 +162,15 @@ VLDBInit(int noAuthFlag, struct afsconf_cell *info) return code; } -FILE *OpenFile(char *file, char *rwp) +static FILE * +OpenFile(char *file, char *rwp) { char wdir[256]; long code; long tlen; FILE *fp; - code = GetWindowsDirectory(wdir, sizeof(wdir)); + code = GetWindowsDirectoryA(wdir, sizeof(wdir)); if (code == 0 || code > sizeof(wdir)) return FALSE; @@ -135,7 +216,7 @@ void Flush(const CStringArray& files) for (int i = 0; i < files.GetSize(); i++) { blob.in_size = blob.out_size = 0; - code = pioctl(PCCHAR(files[i]), VIOCFLUSH, &blob, 0); + code = pioctl_T(files[i], VIOCFLUSH, &blob, 0); if (code) { error = 1; if (errno == EMFILE) @@ -160,7 +241,7 @@ void FlushVolume(const CStringArray& files) for (int i = 0; i < files.GetSize(); i++) { blob.in_size = blob.out_size = 0; - code = pioctl(PCCHAR(files[i]), VIOC_FLUSHVOLUME, &blob, 0); + code = pioctl_T(files[i], VIOC_FLUSHVOLUME, &blob, 0); if (code) { error = 1; ShowMessageBox(IDS_FLUSH_VOLUME_ERROR, MB_ICONERROR, IDS_FLUSH_VOLUME_ERROR, files[i], strerror(errno)); @@ -190,15 +271,16 @@ void WhichCell(CStringArray& files) blob.out_size = MAXSIZE; blob.out = space; - code = pioctl(PCCHAR(files[i]), VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_T(files[i], VIOC_FILE_CELL_NAME, &blob, 1); if (code) { if (code == ENOENT) { LoadString (str, IDS_CANT_GET_CELL); results.Add(str); } else results.Add(GetAfsError(errno)); - } else - results.Add(space); + } else { + results.Add(Utf8ToCString(space)); + } } LoadString (str, IDS_SHOW_CELL); @@ -282,7 +364,7 @@ void WhereIs(CStringArray& files) blob.out = space; memset(space, 0, sizeof(space)); - code = pioctl(PCCHAR(files[i]), VIOCWHEREIS, &blob, 1); + code = pioctl_T(files[i], VIOCWHEREIS, &blob, 1); if (code) { resultFiles.Add(StripPath(files[i])); servers.Add(GetAfsError(errno)); @@ -355,7 +437,7 @@ CMtoUNIXerror(int cm_code) } } -CString GetAfsError(int code, const char *filename) +CString GetAfsError(int code, const TCHAR *filename) { CString strMsg; @@ -363,28 +445,28 @@ CString GetAfsError(int code, const char *filename) if (code == EINVAL) { if (filename) - strMsg.Format("Invalid argument; it is possible that the file is not in AFS"); + strMsg.Format(_T("Invalid argument; it is possible that the file is not in AFS")); else - strMsg.Format("Invalid argument"); + strMsg.Format(_T("Invalid argument")); } else if (code == ENOENT) { if (filename) - strMsg.Format("The file does not exist"); + strMsg.Format(_T("The file does not exist")); else - strMsg.Format("No such file returned"); + strMsg.Format(_T("No such file returned")); } else if (code == EROFS) { - strMsg.Format("You can not change a backup or readonly volume"); + strMsg.Format(_T("You can not change a backup or readonly volume")); } else if (code == EACCES || code == EPERM) { - strMsg.Format("You do not have the required rights to do this operation"); + strMsg.Format(_T("You do not have the required rights to do this operation")); } else if (code == ENODEV) { - strMsg.Format("AFS service may not have started"); + strMsg.Format(_T("AFS service may not have started")); } else if (code == ESRCH) { - strMsg.Format("Cell name not recognized"); + strMsg.Format(_T("Cell name not recognized")); } else if (code == ETIMEDOUT) { - strMsg.Format("Connection timed out"); + strMsg.Format(_T("Connection timed out")); } else if (code == EPIPE) { - strMsg.Format("Volume name or ID not recognized"); + strMsg.Format(_T("Volume name or ID not recognized")); } else { - strMsg.Format("Error 0x%x occurred", code); + strMsg.Format(_T("Error 0x%x occurred"), code); } return strMsg; @@ -495,23 +577,23 @@ CString GetRightsString(register LONG arights, int dfs) CString str; if (!dfs) { - if (arights & PRSFS_READ) str += "r"; - if (arights & PRSFS_LOOKUP) str += "l"; - if (arights & PRSFS_INSERT) str += "i"; - if (arights & PRSFS_DELETE) str += "d"; - if (arights & PRSFS_WRITE) str += "w"; - if (arights & PRSFS_LOCK) str += "k"; - if (arights & PRSFS_ADMINISTER) str += "a"; + if (arights & PRSFS_READ) str += _T("r"); + if (arights & PRSFS_LOOKUP) str += _T("l"); + if (arights & PRSFS_INSERT) str += _T("i"); + if (arights & PRSFS_DELETE) str += _T("d"); + if (arights & PRSFS_WRITE) str += _T("w"); + if (arights & PRSFS_LOCK) str += _T("k"); + if (arights & PRSFS_ADMINISTER) str += _T("a"); } else { ASSERT(FALSE); /* - if (arights & DFS_READ) str += "r"; else str += "-"; - if (arights & DFS_WRITE) str += "w"; else printf("-"); - if (arights & DFS_EXECUTE) str += "x"; else printf("-"); - if (arights & DFS_CONTROL) str += "c"; else printf("-"); - if (arights & DFS_INSERT) str += "i"; else printf("-"); - if (arights & DFS_DELETE) str += "d"; else printf("-"); - if (arights & (DFS_USRALL)) str += "+"; + if (arights & DFS_READ) str += _T("r"); else str += _T("-"); + if (arights & DFS_WRITE) str += _T("w"); else printf(_T("-")); + if (arights & DFS_EXECUTE) str += _T("x"); else printf(_T("-")); + if (arights & DFS_CONTROL) str += _T("c"); else printf(_T("-")); + if (arights & DFS_INSERT) str += _T("i"); else printf(_T("-")); + if (arights & DFS_DELETE) str += _T("d"); else printf(_T("-")); + if (arights & (DFS_USRALL)) str += _T("+"); */ } @@ -547,12 +629,13 @@ char *AclToString(struct Acl *acl) struct Acl *EmptyAcl(const CString& strCellName) { register struct Acl *tp; + CStringUtf8 ustrCell(strCellName); tp = (struct Acl *)malloc(sizeof (struct Acl)); tp->nplus = tp->nminus = 0; tp->pluslist = tp->minuslist = 0; tp->dfs = 0; - strcpy(tp->cell, strCellName); + StringCbCopyA(tp->cell, sizeof(tp->cell), ustrCell); return tp; } @@ -643,7 +726,6 @@ ParseAcl (char *astr) } ta->minuslist = first; - exit: return ta; nminus_err: @@ -725,7 +807,7 @@ void CleanACL(CStringArray& names) blob.in_size = 0; blob.out = space; - code = pioctl(PCCHAR(names[i]), VIOCGETAL, &blob, 1); + code = pioctl_T(names[i], VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_CLEANACL_ERROR, MB_ICONERROR, 0, names[i], GetAfsError(errno)); continue; @@ -750,7 +832,7 @@ void CleanACL(CStringArray& names) blob.in_size = strlen((char *)blob.in) + 1; blob.out_size = 0; - code = pioctl(PCCHAR(names[i]), VIOCSETAL, &blob, 1); + code = pioctl_T(names[i], VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) { ShowMessageBox(IDS_CLEANACL_INVALID_ARG, MB_ICONERROR, IDS_CLEANACL_INVALID_ARG, names[i]); @@ -779,7 +861,7 @@ BOOL GetRights(const CString& strDir, CStringArray& strNormal, CStringArray& str blob.in_size = idf; blob.in = blob.out = space; - code = pioctl(PCCHAR(strDir), VIOCGETAL, &blob, 1); + code = pioctl_T(strDir, VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_GETRIGHTS_ERROR, MB_ICONERROR, IDS_GETRIGHTS_ERROR, strDir, GetAfsError(errno)); return FALSE; @@ -828,17 +910,18 @@ struct AclEntry *FindList(register struct AclEntry *pCurEntry, const char *entry return 0; } -void ChangeList (struct Acl *pAcl, BYTE bNormalRights, const char *entryName, LONG nEntryRights) +void ChangeList(struct Acl *pAcl, BYTE bNormalRights, const CString & entryName, LONG nEntryRights) { ASSERT(pAcl); ASSERT(entryName); struct AclEntry *pEntry; + CStringUtf8 uEntryName(entryName); HOURGLASS hourglass; pEntry = (bNormalRights ? pAcl->pluslist : pAcl->minuslist); - pEntry = FindList(pEntry, entryName); + pEntry = FindList(pEntry, uEntryName); /* Found the item already in the list. */ if (pEntry) { @@ -854,7 +937,7 @@ void ChangeList (struct Acl *pAcl, BYTE bNormalRights, const char *entryName, LO pEntry = (struct AclEntry *) malloc(sizeof (struct AclEntry)); ASSERT(pEntry); - strcpy(pEntry->name, entryName); + strcpy(pEntry->name, uEntryName); pEntry->rights = nEntryRights; if (bNormalRights) { @@ -875,42 +958,41 @@ void ChangeList (struct Acl *pAcl, BYTE bNormalRights, const char *entryName, LO enum rtype {add, destroy, deny}; -LONG Convert(const register char *arights, int dfs, enum rtype *rtypep) +static LONG Convert(const CString& strRights, int dfs, enum rtype *rtypep) { register int i, len; LONG mode; - register char tc; *rtypep = add; /* add rights, by default */ - if (!strcmp(arights,"read")) + if (strRights == _T("read")) return PRSFS_READ | PRSFS_LOOKUP; - if (!strcmp(arights, "write")) + if (strRights == _T("write")) return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK; - if (!strcmp(arights, "mail")) + if (strRights == _T("mail")) return PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP; - if (!strcmp(arights, "all")) + if (strRights == _T("all")) return PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE | PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER; - if (!strcmp(arights, "none")) { + if (strRights == _T("none")) { *rtypep = destroy; /* Remove entire entry */ return 0; } - len = strlen(arights); + len = strRights.GetLength(); mode = 0; for (i = 0; i < len; i++) { - tc = *arights++; - if (tc == 'r') mode |= PRSFS_READ; - else if (tc == 'l') mode |= PRSFS_LOOKUP; - else if (tc == 'i') mode |= PRSFS_INSERT; - else if (tc == 'd') mode |= PRSFS_DELETE; - else if (tc == 'w') mode |= PRSFS_WRITE; - else if (tc == 'k') mode |= PRSFS_LOCK; - else if (tc == 'a') mode |= PRSFS_ADMINISTER; + TCHAR c = strRights[i]; + if (c == _T('r')) mode |= PRSFS_READ; + else if (c == _T('l')) mode |= PRSFS_LOOKUP; + else if (c == _T('i')) mode |= PRSFS_INSERT; + else if (c == _T('d')) mode |= PRSFS_DELETE; + else if (c == _T('w')) mode |= PRSFS_WRITE; + else if (c == _T('k')) mode |= PRSFS_LOCK; + else if (c == _T('a')) mode |= PRSFS_ADMINISTER; else { - fprintf(stderr, "illegal rights character '%c'.\n", tc); + fprintf(stderr, "illegal rights character '%c'.\n", c); exit(1); } } @@ -948,7 +1030,7 @@ BOOL SaveACL(const CString& strCellName, const CString& strDir, const CStringArr blob.out_size = 0; blob.in_size = 1 + strlen((const char *)blob.in); - code = pioctl(PCCHAR(strDir), VIOCSETAL, &blob, 1); + code = pioctl_T(strDir, VIOCSETAL, &blob, 1); if (code) { if (errno == EINVAL) ShowMessageBox(IDS_SAVE_ACL_EINVAL_ERROR, MB_ICONERROR, IDS_SAVE_ACL_EINVAL_ERROR, strDir); @@ -975,7 +1057,7 @@ BOOL CopyACL(const CString& strToDir, const CStringArray& normal, const CStringA blob.in_size = idf; blob.in = blob.out = space; - code = pioctl(PCCHAR(strToDir), VIOCGETAL, &blob, 1); + code = pioctl_T(strToDir, VIOCGETAL, &blob, 1); if (code) { ShowMessageBox(IDS_ACL_READ_ERROR, MB_ICONERROR, IDS_ACL_READ_ERROR, strToDir, GetAfsError(errno, strToDir)); return FALSE; @@ -1019,7 +1101,7 @@ BOOL CopyACL(const CString& strToDir, const CStringArray& normal, const CStringA blob.out_size = 0; blob.in_size = 1 + strlen((char *)blob.in); - code = pioctl(PCCHAR(strToDir), VIOCSETAL, &blob, 1); + code = pioctl_T(strToDir, VIOCSETAL, &blob, 1); if (code) { ZapAcl(pToAcl); if (errno == EINVAL) @@ -1055,7 +1137,7 @@ CString ParseMountPoint(const CString strFile, CString strMountPoint) } else strVolume = strMountPoint.Mid(1); - strMountPointInfo = strFile + "\t" + strVolume + "\t" + strCell + "\t" + strType; + strMountPointInfo = strFile + _T("\t") + strVolume + _T("\t") + strCell + _T("\t") + strType; return strMountPointInfo; } @@ -1064,30 +1146,31 @@ CString ParseSymlink(const CString strFile, CString strSymlink) { CString strSymlinkInfo; - strSymlinkInfo = strFile + "\t" + strSymlink; + strSymlinkInfo = strFile + _T("\t") + strSymlink; return strSymlinkInfo; } -BOOL IsPathInAfs(const CHAR *strPath) +BOOL IsPathInAfs(const CString & strPath) { struct ViceIoctl blob; int code; HOURGLASS hourglass; - char buf[512]; - sprintf(buf, "IsPathInAfs(%s)", strPath); - OutputDebugString(buf); + CString debugBuf; + + debugBuf.Format(_T("IsPathInAfs(%s)"), strPath); + OutputDebugString(debugBuf); blob.in_size = 0; blob.out_size = MAXSIZE; blob.out = space; - code = pioctl((LPTSTR)((LPCTSTR)strPath), VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_T(strPath, VIOC_FILE_CELL_NAME, &blob, 1); - sprintf(buf, "VIOC_FILE_CELL_NAME=%d", code); - OutputDebugString(buf); + debugBuf.Format(_T("VIOC_FILE_CELL_NAME=%d"), code); + OutputDebugString(debugBuf); if (code) { if ((errno == EINVAL) || (errno == ENOENT)) @@ -1097,7 +1180,7 @@ BOOL IsPathInAfs(const CHAR *strPath) } static int -IsFreelanceRoot(char *apath) +IsFreelanceRoot(const CString& apath) { struct ViceIoctl blob; afs_int32 code; @@ -1106,13 +1189,13 @@ IsFreelanceRoot(char *apath) blob.out_size = MAXSIZE; blob.out = space; - code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1); + code = pioctl_T(apath, VIOC_FILE_CELL_NAME, &blob, 1); if (code == 0) return !strcmp("Freelance.Local.Root",space); return 1; /* assume it is because it is more restrictive that way */ } -const char * NetbiosName(void) +static const char * NetbiosName(void) { static char buffer[1024] = "AFS"; HKEY parmKey; @@ -1120,11 +1203,11 @@ const char * NetbiosName(void) DWORD dummyLen; DWORD enabled = 0; - code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, + code = RegOpenKeyExA(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey); if (code == ERROR_SUCCESS) { dummyLen = sizeof(buffer); - code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL, + code = RegQueryValueExA(parmKey, "NetbiosName", NULL, NULL, (LPBYTE)buffer, &dummyLen); RegCloseKey (parmKey); } else { @@ -1133,6 +1216,24 @@ const char * NetbiosName(void) return buffer; } +static void FixNetbiosPath(CString& path) +{ + if (!IsPathInAfs(path)) { + CString nbroot; + const char * nbname = NetbiosName(); + +#ifdef UNICODE + nbroot.Format(_T("\\\\%S\\"), nbname); +#else + nbroot.Format(_T("\\\\%s\\"), nbname); +#endif + + if (nbroot.CompareNoCase(path) == 0) { + path.Append(_T("all\\")); + } + } +} + #define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins" static BOOL IsAdmin (void) @@ -1147,8 +1248,8 @@ static BOOL IsAdmin (void) */ PSID psidAdmin = NULL; DWORD dwSize, dwSize2; - char pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ]; - char *pszRefDomain = NULL; + TCHAR pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ]; + TCHAR *pszRefDomain = NULL; SID_NAME_USE snu = SidTypeGroup; dwSize = sizeof(pszAdminGroup); @@ -1162,8 +1263,8 @@ static BOOL IsAdmin (void) dwSize = 0; dwSize2 = 0; - strcat(pszAdminGroup,"\\"); - strcat(pszAdminGroup, AFSCLIENT_ADMIN_GROUPNAME); + lstrcat(pszAdminGroup, _T("\\")); + lstrcat(pszAdminGroup, _T(AFSCLIENT_ADMIN_GROUPNAME)); LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu); /* that should always fail. */ @@ -1181,7 +1282,7 @@ static BOOL IsAdmin (void) } psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize); - pszRefDomain = (char *)malloc(dwSize2); + pszRefDomain = (TCHAR *)malloc(dwSize2); if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) { /* We can't lookup the group now even though we looked it up earlier. @@ -1268,36 +1369,63 @@ static BOOL IsAdmin (void) return fAdmin; } -/* return a static pointer to a buffer */ -static char *Parent(char *apath) +CString Parent(const CString& path) { - register char *tp; + int last_slash = path.ReverseFind(_T('\\')); - strcpy(tspace, apath); - tp = strrchr(tspace, '\\'); - if (tp) { - *(tp+1) = 0; /* lv trailing slash so Parent("k:\foo") is "k:\" not "k:" */ + if (last_slash != -1) { + CString ret = path.Left(last_slash + 1); + return ret; + } else { + if (path.GetLength() >= 2 && path[1] == _T(':')) { + CString ret = path.Left(2); + ret.AppendChar(_T('.')); + return ret; + } else { + CString ret = _T("."); + return ret; + } } - else { - fs_ExtractDriveLetter(apath, tspace); - strcat(tspace, "."); } - return tspace; +CString LastComponent(const CString& path) +{ + int last_slash = path.ReverseFind(_T('\\')); + + if (last_slash != -1) { + CString ret = path.Mid(last_slash + 1); + return ret; + } else { + if (path.GetLength() >= 2 && path[1] == _T(':')) { + CString ret = path.Mid(2); + return ret; + } else { + CString ret = path; + return ret; + } + } } -static afs_int32 -GetCell(char *fname, char *cellname) +static CString +GetCell(const CString & path) { + char cellname[MAXCELLCHARS]; afs_int32 code; struct ViceIoctl blob; blob.in_size = 0; - blob.out_size = MAXCELLCHARS; + blob.out_size = sizeof(cellname); blob.out = cellname; - code = pioctl(fname, VIOC_FILE_CELL_NAME, &blob, 1); - return code ? errno : 0; + code = pioctl_T(path, VIOC_FILE_CELL_NAME, &blob, 1); + if (code) { + CString s; + s.Empty(); + + return s; + } else { + return Utf8ToCString(cellname); + } } @@ -1306,10 +1434,10 @@ BOOL ListMount(CStringArray& files) register LONG code; struct ViceIoctl blob; int error; - char orig_name[1024]; /* Original name, may be modified */ - char true_name[1024]; /* ``True'' dirname (e.g., symlink target) */ - char parent_dir[1024]; /* Parent directory of true name */ - register char *last_component; /* Last component of true name */ + + CString parent_dir; /* Parent directory of true name */ + CStringUtf8 last_component; /* Last component of true name */ + CStringArray mountPoints; HOURGLASS hourglass; @@ -1317,58 +1445,41 @@ BOOL ListMount(CStringArray& files) error = 0; for (int i = 0; i < files.GetSize(); i++) { - strcpy(orig_name, files[i]); - strcpy(true_name, orig_name); + int last_slash = files[i].ReverseFind(_T('\\')); - /* - * Find rightmost slash, if any. - */ - last_component = (char *)strrchr(true_name, '\\'); - if (last_component) { - /* - * Found it. Designate everything before it as the parent directory, - * everything after it as the final component. - */ - strncpy(parent_dir, true_name, last_component - true_name + 1); - parent_dir[last_component - true_name + 1] = 0; - last_component++; /* Skip the slash */ + if (last_slash != -1) { + last_component.SetString( files[i].Mid(last_slash + 1) ); + parent_dir.SetString( files[i].Left(last_slash + 1) ); + FixNetbiosPath(parent_dir); + } else { + // The path is of the form "C:foo" or just "foo". If + // there is a drive, then use the current directory of + // that drive. Otherwise we just use '.'. - if (!IsPathInAfs(parent_dir)) { - const char * nbname = NetbiosName(); - int len = strlen(nbname); - - if (parent_dir[0] == '\\' && parent_dir[1] == '\\' && - parent_dir[len+2] == '\\' && - parent_dir[len+3] == '\0' && - !strnicmp(nbname,&parent_dir[2],len)) - { - sprintf(parent_dir,"\\\\%s\\all\\", nbname); - } + if (files[i].GetLength() >= 2 && files[i][1] == _T(':')) { + parent_dir.Format(_T("%c:."), files[i][0]); + last_component.SetString( files[i].Mid(2) ); + } else { + parent_dir.SetString( _T(".")); + last_component.SetString( files[i] ); } } - else { - /* - * No slash appears in the given file name. Set parent_dir to the current - * directory, and the last component as the given name. - */ - fs_ExtractDriveLetter(true_name, parent_dir); - strcat(parent_dir, "."); - last_component = true_name; - fs_StripDriveLetter(true_name, true_name, sizeof(true_name)); - } - blob.in = last_component; - blob.in_size = strlen(last_component) + 1; + blob.in_size = last_component.GetLength() + 1; + blob.in = last_component.GetBuffer(); blob.out_size = MAXSIZE; blob.out = space; memset(space, 0, MAXSIZE); - code = pioctl(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1); + code = pioctl_T(parent_dir, VIOC_AFS_STAT_MT_PT, &blob, 1); + + last_component.ReleaseBuffer(); + if (code == 0) { int nPos = strlen(space) - 1; if (space[nPos] == '.') space[nPos] = 0; - mountPoints.Add(ParseMountPoint(StripPath(files[i]), space)); + mountPoints.Add(ParseMountPoint(StripPath(files[i]), Utf8ToCString(space))); } else { error = 1; if (errno == EINVAL) @@ -1385,113 +1496,52 @@ BOOL ListMount(CStringArray& files) return !error; } -BOOL MakeMount(const CString& strDir, const CString& strVolName, const CString& strCellName, BOOL bRW) +BOOL +MakeMount(const CString& strDir, + const CString& strVolName, + const CString& strInCellName, + BOOL bRW) { - register LONG code; - register char *cellName; - char localCellName[128]; - struct afsconf_cell info; -#if 0 - struct vldbentry vldbEntry; -#endif + LONG code; struct ViceIoctl blob; - char * parent; - char path[1024] = ""; - HOURGLASS hourglass; ASSERT(strVolName.GetLength() < 64); - if (strCellName.GetLength() > 0) /* cell name specified */ - cellName = PCCHAR(strCellName); - else - cellName = (char *) 0; + CString strParent = Parent(strDir); - parent = Parent(PCCHAR(strDir)); - if (!IsPathInAfs(parent)) { - const char * nbname = NetbiosName(); - int len = strlen(nbname); - - if (parent[0] == '\\' && parent[1] == '\\' && - parent[len+2] == '\\' && - parent[len+3] == '\0' && - !strnicmp(nbname,&parent[2],len)) - { - sprintf(path,"%sall\\%s", parent, &(PCCHAR(strDir)[strlen(parent)])); - parent = Parent(path); - if (!IsPathInAfs(parent)) { - ShowMessageBox(IDS_MAKE_MP_NOT_AFS_ERROR, MB_ICONERROR, IDS_MAKE_MP_NOT_AFS_ERROR); - return FALSE; - } - } else { + FixNetbiosPath(strParent); + if (!IsPathInAfs(strParent)) { ShowMessageBox(IDS_MAKE_MP_NOT_AFS_ERROR, MB_ICONERROR, IDS_MAKE_MP_NOT_AFS_ERROR); return FALSE; } - } - if ( strlen(path) == 0 ) - strcpy(path, PCCHAR(strDir)); + CString strPath = strParent + LastComponent(strDir); - if ( IsFreelanceRoot(parent) ) { - if ( !IsAdmin() ) { - ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR); + if ( IsFreelanceRoot(strParent) && !IsAdmin() ) { + ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, + IDS_NOT_AFS_CLIENT_ADMIN_ERROR); return FALSE; } - if (!cellName) { - blob.in_size = 0; - blob.out_size = sizeof(localCellName); - blob.out = localCellName; - code = pioctl(parent, VIOC_GET_WS_CELL, &blob, 1); - if (!code) - cellName = localCellName; - } - } else { - if (!cellName) - GetCell(parent,space); - } + CString strMount; - code = GetCellName(cellName?cellName:space, &info); - if (code) { - return FALSE; - } + strMount.Format(_T("%c%s%s%s."), + ((bRW)?_T('%'):_T('#')), + strInCellName, + ((strInCellName.IsEmpty())?_T(""):_T(":")), + strVolName); -#if 0 - code = VLDBInit(1, &info); - if (code == 0) { - /* make the check. Don't complain if there are problems with init */ - code = ubik_VL_GetEntryByNameO(uclient, 0, PCCHAR(strVolName), &vldbEntry); - if (code == VL_NOENT) { - ShowMessageBox(IDS_WARNING, MB_ICONWARNING, IDS_VOLUME_NOT_IN_CELL_WARNING, - PCCHAR(strVolName), cellName ? cellName : space); - } - } - if (rxInitDone) - rx_Finalize(); -#endif + CStringUtf8 ustrMount(strMount); - if (bRW) /* if -rw specified */ - strcpy(space, "%"); - else - strcpy(space, "#"); - - /* If cellular mount point, prepend cell prefix */ - if (cellName) { - strcat(space, info.name); - strcat(space, ":"); - } - - strcat(space, strVolName); /* append volume name */ - strcat(space, "."); /* stupid convention; these end with a period */ - - /* create symlink with a special pioctl for Windows NT, since it doesn't - * have a symlink system call. - */ blob.out_size = 0; - blob.in_size = 1 + strlen(space); - blob.in = space; + blob.in_size = ustrMount.GetLength() + 1; + blob.in = ustrMount.GetBuffer(); blob.out = NULL; - code = pioctl(path, VIOC_AFS_CREATE_MT_PT, &blob, 0); + + code = pioctl_T(strPath, VIOC_AFS_CREATE_MT_PT, &blob, 0); + + ustrMount.ReleaseBuffer(); if (code) { ShowMessageBox(IDS_MOUNT_POINT_ERROR, MB_ICONERROR, IDS_MOUNT_POINT_ERROR, GetAfsError(errno, strDir)); @@ -1533,178 +1583,112 @@ long fs_StripDriveLetter(const char *inPathp, char *outPathp, long outSize) } -BOOL RemoveSymlink(const char * linkName) +BOOL RemoveSymlink(const CString& strName) { BOOL error = FALSE; INT code=0; struct ViceIoctl blob; - char tbuffer[1024]; char lsbuffer[1024]; - char tpbuffer[1024]; - char *tp; HOURGLASS hourglass; - tp = (char *) strrchr(linkName, '\\'); - if (!tp) - tp = (char *) strrchr(linkName, '/'); - if (tp) { - strncpy(tbuffer, linkName, code=tp-linkName+1); /* the dir name */ - tbuffer[code] = 0; - tp++; /* skip the slash */ + CString strParent = Parent(strName); + CStringUtf8 ustrLast(LastComponent(strName)); + FixNetbiosPath(strParent); - if (!IsPathInAfs(tbuffer)) { - const char * nbname = NetbiosName(); - int len = strlen(nbname); - - if (tbuffer[0] == '\\' && tbuffer[1] == '\\' && - tbuffer[len+2] == '\\' && - tbuffer[len+3] == '\0' && - !strnicmp(nbname,&tbuffer[2],len)) - { - sprintf(tbuffer,"\\\\%s\\all\\", nbname); - } - } - } - else { - fs_ExtractDriveLetter(linkName, tbuffer); - strcat(tbuffer, "."); - fs_StripDriveLetter(tp, tpbuffer, 0); - tp=tpbuffer; - } - - if ( IsFreelanceRoot(tbuffer) && !IsAdmin() ) { + if ( IsFreelanceRoot(strParent) && !IsAdmin() ) { ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR); return FALSE; } - blob.in = tp; - blob.in_size = strlen(tp)+1; + blob.in_size = ustrLast.GetLength() + 1; + blob.in = ustrLast.GetBuffer(); blob.out = lsbuffer; blob.out_size = sizeof(lsbuffer); - code = pioctl(tbuffer, VIOC_LISTSYMLINK, &blob, 0); + code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 0); + ustrLast.ReleaseBuffer(); if (code) return FALSE; blob.out_size = 0; - blob.in = tp; - blob.in_size = strlen(tp)+1; - return (pioctl(tbuffer, VIOC_DELSYMLINK, &blob, 0)==0); + blob.in_size = ustrLast.GetLength() + 1; + blob.in = ustrLast.GetBuffer(); + + code = pioctl_T(strParent, VIOC_DELSYMLINK, &blob, 0); + + ustrLast.ReleaseBuffer(); + + return (code == 0); } -BOOL IsSymlink(const char * true_name) +BOOL IsSymlink(const CString& strName) { - char parent_dir[MAXSIZE]; /*Parent directory of true name*/ - char strip_name[MAXSIZE]; struct ViceIoctl blob; - char *last_component; int code; HOURGLASS hourglass; - char buf[512]; - sprintf(buf, "IsSymlink(%s)", true_name); - OutputDebugString(buf); - - last_component = (char *) strrchr(true_name, '\\'); - if (!last_component) - last_component = (char *) strrchr(true_name, '/'); - if (last_component) { - /* - * Found it. Designate everything before it as the parent directory, - * everything after it as the final component. - */ - strncpy(parent_dir, true_name, last_component - true_name + 1); - parent_dir[last_component - true_name + 1] = 0; - last_component++; /*Skip the slash*/ - - if (!IsPathInAfs(parent_dir)) { - const char * nbname = NetbiosName(); - int len = strlen(nbname); - - if (parent_dir[0] == '\\' && parent_dir[1] == '\\' && - parent_dir[len+2] == '\\' && - parent_dir[len+3] == '\0' && - !strnicmp(nbname,&parent_dir[2],len)) { - sprintf(parent_dir,"\\\\%s\\all\\", nbname); - } - } - } - else { - /* - * No slash appears in the given file name. Set parent_dir to the current - * directory, and the last component as the given name. - */ - fs_ExtractDriveLetter(true_name, parent_dir); - strcat(parent_dir, "."); - last_component = strip_name; - fs_StripDriveLetter(true_name, strip_name, sizeof(strip_name)); + CString str; + str.Format(_T("IsSymlink(%s)"), strName); + OutputDebugString(str); } - sprintf(buf, "last_component=%s", last_component); - OutputDebugString(buf); + CStringUtf8 ustrLast(LastComponent(strName)); + CString strParent = Parent(strName); - blob.in = last_component; - blob.in_size = strlen(last_component)+1; + FixNetbiosPath(strParent); + + blob.in_size = ustrLast.GetLength() + 1; + blob.in = ustrLast.GetBuffer(); blob.out_size = MAXSIZE; blob.out = space; memset(space, 0, MAXSIZE); - code = pioctl(parent_dir, VIOC_LISTSYMLINK, &blob, 1); + + code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1); + + ustrLast.ReleaseBuffer(); + return (code==0); } -BOOL IsMountPoint(const char * name) +BOOL IsMountPoint(const CString& path) { register LONG code = 0; struct ViceIoctl blob; - char tbuffer[1024]; char lsbuffer[1024]; - register char *tp; - char szCurItem[1024]; HOURGLASS hourglass; - strcpy(szCurItem, name); - - char buf[512]; - sprintf(buf, "IsMountPoint(%s)", name); - OutputDebugString(buf); - - tp = (char *)strrchr(szCurItem, '\\'); - if (tp) { - strncpy(tbuffer, szCurItem, code = tp - szCurItem + 1); /* the dir name */ - tbuffer[code] = 0; - tp++; /* skip the slash */ - - if (!IsPathInAfs(tbuffer)) { - const char * nbname = NetbiosName(); - int len = strlen(nbname); - - if (tbuffer[0] == '\\' && tbuffer[1] == '\\' && - tbuffer[len+2] == '\\' && - tbuffer[len+3] == '\0' && - !strnicmp(nbname,&tbuffer[2],len)) - { - sprintf(tbuffer,"\\\\%s\\all\\", nbname); - } - } - } else { - fs_ExtractDriveLetter(szCurItem, tbuffer); - strcat(tbuffer, "."); - tp = szCurItem; - fs_StripDriveLetter(tp, tp, 0); + { + CString str; + str.Format(_T("IsMountPoint(%s)"), path); + OutputDebugString(str); } - sprintf(buf, "last_component=%s", tp); - OutputDebugString(buf); + CString parent = Parent(path); + FixNetbiosPath(parent); - blob.in = tp; - blob.in_size = strlen(tp)+1; + CStringUtf8 mountpoint(LastComponent(path)); + + { + CString str; +#ifdef UNICODE + str.Format(_T("last_component=%S"), mountpoint); +#else + str.Format(_T("last_component=%s"), mountpoint); +#endif + OutputDebugString(str); + } + + blob.in_size = mountpoint.GetLength() + 1; + blob.in = mountpoint.GetBuffer(); blob.out = lsbuffer; blob.out_size = sizeof(lsbuffer); - code = pioctl(tbuffer, VIOC_AFS_STAT_MT_PT, &blob, 0); + code = pioctl_T(parent, VIOC_AFS_STAT_MT_PT, &blob, 0); + + mountpoint.ReleaseBuffer(); return (code==0); } @@ -1720,9 +1704,6 @@ BOOL RemoveMount(CStringArray& files) { register LONG code = 0; struct ViceIoctl blob; - char tbuffer[1024]; - register char *tp; - char szCurItem[1024]; BOOL error = FALSE; CStringArray results; CString str; @@ -1740,44 +1721,24 @@ BOOL RemoveMount(CStringArray& files) continue; // don't bother trying } - strcpy(szCurItem, files[i]); - - tp = (char *)strrchr(szCurItem, '\\'); - if (tp) { - strncpy(tbuffer, szCurItem, code = tp - szCurItem + 1); /* the dir name */ - tbuffer[code] = 0; - tp++; /* skip the slash */ + CString parent = Parent(files[i]); + CStringUtf8 mountpoint(LastComponent(files[i])); + FixNetbiosPath(parent); - if (!IsPathInAfs(tbuffer)) { - const char * nbname = NetbiosName(); - int len = strlen(nbname); - - if (tbuffer[0] == '\\' && tbuffer[1] == '\\' && - tbuffer[len+2] == '\\' && - tbuffer[len+3] == '\0' && - !strnicmp(nbname,&tbuffer[2],len)) - { - sprintf(tbuffer,"\\\\%s\\all\\", nbname); - } - } - } else { - fs_ExtractDriveLetter(szCurItem, tbuffer); - strcat(tbuffer, "."); - tp = szCurItem; - fs_StripDriveLetter(tp, tp, 0); - } - - if ( IsFreelanceRoot(tbuffer) && !IsAdmin() ) { + if ( IsFreelanceRoot(parent) && !IsAdmin() ) { results.Add(GetMessageString(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, StripPath(files[i]))); error = TRUE; continue; /* skip */ } blob.out_size = 0; - blob.in = tp; - blob.in_size = strlen(tp)+1; + blob.in_size = mountpoint.GetLength() + 1; + blob.in = mountpoint.GetBuffer(); + + code = pioctl_T(parent, VIOC_AFS_DELETE_MT_PT, &blob, 0); + + mountpoint.ReleaseBuffer(); - code = pioctl(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0); if (code) { error = TRUE; results.Add(GetMessageString(IDS_ERROR, GetAfsError(errno, StripPath(files[i])))); @@ -1822,7 +1783,7 @@ BOOL GetVolumeInfo(CString strFile, CVolInfo& volInfo) blob.in_size = 0; blob.out = space; - code = pioctl(PCCHAR(strFile), VIOCGETVOLSTAT, &blob, 1); + code = pioctl_T(strFile, VIOCGETVOLSTAT, &blob, 1); if (code) { volInfo.m_strErrorMsg = GetAfsError(errno, strFile); return FALSE; @@ -1831,7 +1792,7 @@ BOOL GetVolumeInfo(CString strFile, CVolInfo& volInfo) status = (VolumeStatus *)space; name = (char *)status + sizeof(*status); - volInfo.m_strName = name; + volInfo.m_strName = Utf8ToCString(name); volInfo.m_nID = status->Vid; volInfo.m_nQuota = status->MaxQuota; volInfo.m_nNewQuota = status->MaxQuota; @@ -1881,7 +1842,7 @@ BOOL SetVolInfo(CVolInfo& volInfo) } #endif - code = pioctl(PCCHAR(volInfo.m_strFilePath), VIOCSETVOLSTAT, &blob, 1); + code = pioctl_T(volInfo.m_strFilePath, VIOCSETVOLSTAT, &blob, 1); if (code) { ShowMessageBox(IDS_SET_QUOTA_ERROR, MB_ICONERROR, IDS_SET_QUOTA_ERROR, GetAfsError(errno, volInfo.m_strName)); return FALSE; @@ -1890,10 +1851,11 @@ BOOL SetVolInfo(CVolInfo& volInfo) return TRUE; } -int GetCellName(char *cellNamep, struct afsconf_cell *infop) +void GetCellName(const CString& cellNamep, struct afsconf_cell *infop) { - strcpy(infop->name, cellNamep); - return 0; + CStringUtf8 uCellName(cellNamep); + + StringCbCopyA(infop->name, sizeof(infop->name), uCellName); } BOOL CheckServers(const CString& strCellName, WHICH_CELLS nCellsToCheck, BOOL bFast) @@ -1917,7 +1879,7 @@ BOOL CheckServers(const CString& strCellName, WHICH_CELLS nCellsToCheck, BOOL bF if (nCellsToCheck == SPECIFIC_CELL) { temp = 2; - GetCellName(PCCHAR(strCellName), &info); + GetCellName(strCellName, &info); strcpy(checkserv.tbuffer,info.name); checkserv.tsize = strlen(info.name) + 1; } else { @@ -1933,7 +1895,7 @@ BOOL CheckServers(const CString& strCellName, WHICH_CELLS nCellsToCheck, BOOL bF checkserv.tflags = temp; checkserv.tinterval = -1; /* don't change current interval */ - code = pioctl(0, VIOCCKSERV, &blob, 1); + code = pioctl_utf8(0, VIOCCKSERV, &blob, 1); if (code) { ShowMessageBox(IDS_CHECK_SERVERS_ERROR, MB_ICONERROR, IDS_CHECK_SERVERS_ERROR, GetAfsError(errno, CString())); return FALSE; @@ -2049,7 +2011,11 @@ BOOL GetTokenInfo(CStringArray& tokenInfo) expireString += 4; /* Skip day of week */ expireString[12] = '\0'; /* Omit secs & year */ // printf("[Expires %s]\n", expireString); - strExpir.Format("%s", expireString); +#ifdef UNICODE + strExpir.Format(_T("%S"), expireString); +#else + strExpir.Format(_T("%s"), expireString); +#endif } strTokenInfo = strUserName + "\t" + strCellName + "\t" + strExpir + "\t" + strCellName; @@ -2062,40 +2028,41 @@ BOOL GetTokenInfo(CStringArray& tokenInfo) return TRUE; } -UINT MakeSymbolicLink(const char *strName, const char *strTarget) +UINT MakeSymbolicLink(const CString& strName, const CString& strTarget) { struct ViceIoctl blob; - char space[MAXSIZE]; - char * parent; - char path[1024] = ""; UINT code; - HOURGLASS hourglass; - static char message[2048]; - strcpy(path, strName); - parent = Parent(path); + CString strParent = Parent(strName); + FixNetbiosPath(strParent); - sprintf(message,"MakeSymbolicLink: name = %s target = %s parent = %s\n",strName,strTarget, parent); - OutputDebugString(message); + { + CString str; + str.Format(_T("MakeSymbolicLink: name = %s target = %s parent = %s\n"), + strName, strTarget, strParent); + OutputDebugString(str); + } - if ( IsFreelanceRoot(parent) && !IsAdmin() ) { + if ( IsFreelanceRoot(strParent) && !IsAdmin() ) { ShowMessageBox(IDS_NOT_AFS_CLIENT_ADMIN_ERROR, MB_ICONERROR, IDS_NOT_AFS_CLIENT_ADMIN_ERROR); return FALSE; } - LPTSTR lpsz = new TCHAR[strlen(strTarget)+1]; - _tcscpy(lpsz, strName); - strcpy(space, strTarget); + CStringUtf8 ustrTarget(strTarget); + + blob.in_size = ustrTarget.GetLength() + 1; + blob.in = ustrTarget.GetBuffer(); blob.out_size = 0; - blob.in_size = 1 + strlen(space); - blob.in = space; blob.out = NULL; - code=pioctl(lpsz, VIOC_SYMLINK, &blob, 0); - delete lpsz; + + code = pioctl_T(strName, VIOC_SYMLINK, &blob, 0); + + ustrTarget.ReleaseBuffer(); + if (code != 0) return code; - return FALSE; + return 0; } void ListSymbolicLinkPath(const char *strName,char *strPath,UINT nlenPath) @@ -2166,10 +2133,6 @@ BOOL ListSymlink(CStringArray& files) register LONG code; struct ViceIoctl blob; int error; - char orig_name[1024]; /* Original name, may be modified */ - char true_name[1024]; /* ``True'' dirname (e.g., symlink target) */ - char parent_dir[1024]; /* Parent directory of true name */ - register char *last_component; /* Last component of true name */ CStringArray symlinks; HOURGLASS hourglass; @@ -2177,58 +2140,33 @@ BOOL ListSymlink(CStringArray& files) error = 0; for (int i = 0; i < files.GetSize(); i++) { - strcpy(orig_name, files[i]); - strcpy(true_name, orig_name); - /* - * Find rightmost slash, if any. - */ - last_component = (char *)strrchr(true_name, '\\'); - if (last_component) { - /* - * Found it. Designate everything before it as the parent directory, - * everything after it as the final component. - */ - strncpy(parent_dir, true_name, last_component - true_name + 1); - parent_dir[last_component - true_name + 1] = 0; - last_component++; /* Skip the slash */ + CString strParent = Parent(files[i]); + CStringUtf8 ustrLast(LastComponent(files[i])); - if (!IsPathInAfs(parent_dir)) { - const char * nbname = NetbiosName(); - int len = strlen(nbname); + FixNetbiosPath(strParent); - if (parent_dir[0] == '\\' && parent_dir[1] == '\\' && - parent_dir[len+2] == '\\' && - parent_dir[len+3] == '\0' && - !strnicmp(nbname,&parent_dir[2],len)) - { - sprintf(parent_dir,"\\\\%s\\all\\", nbname); - } - } - } - else { - /* - * No slash appears in the given file name. Set parent_dir to the current - * directory, and the last component as the given name. - */ - fs_ExtractDriveLetter(true_name, parent_dir); - strcat(parent_dir, "."); - last_component = true_name; - fs_StripDriveLetter(true_name, true_name, sizeof(true_name)); - } - - blob.in = last_component; - blob.in_size = strlen(last_component) + 1; + blob.in_size = ustrLast.GetLength() + 1; + blob.in = ustrLast.GetBuffer(); blob.out_size = MAXSIZE; blob.out = space; memset(space, 0, MAXSIZE); - code = pioctl(parent_dir, VIOC_LISTSYMLINK, &blob, 1); + code = pioctl_T(strParent, VIOC_LISTSYMLINK, &blob, 1); + + ustrLast.ReleaseBuffer(); + if (code == 0) { - int nPos = strlen(space) - 1; - if (space[nPos] == '.') - space[nPos] = 0; - symlinks.Add(ParseSymlink(StripPath(files[i]), space)); + CString syml = Utf8ToCString(space); + int len = syml.GetLength(); + + if (len > 0) { + if (syml[len - 1] == _T('.')) + syml.Truncate(len - 1); + } + + symlinks.Add(ParseSymlink(StripPath(files[i]), syml)); + } else { error = 1; if (errno == EINVAL) diff --git a/src/WINNT/client_exp/gui2fs.h b/src/WINNT/client_exp/gui2fs.h index dccd1f3dc9..4c6cbddc61 100644 --- a/src/WINNT/client_exp/gui2fs.h +++ b/src/WINNT/client_exp/gui2fs.h @@ -18,9 +18,8 @@ void WSCellCmd(); void WhichCell(CStringArray& files); BOOL CheckVolumes(); void SetCacheSize(LONG nNewCacheSize); -void RemoveMountCmd(const CStringArray& files); void WhereIs(CStringArray& files); -CString GetAfsError(int code, const char *filename = 0); +CString GetAfsError(int code, const TCHAR *filename = 0); void CleanACL(CStringArray& names); BOOL GetRights(const CString& strDir, CStringArray& strNormal, CStringArray& strNegative); BOOL SaveACL(const CString& strCellName, const CString& strDir, const CStringArray& normal, const CStringArray& negative); @@ -28,20 +27,16 @@ BOOL CopyACL(const CString& strToDir, const CStringArray& normal, const CStringA BOOL ListMount(CStringArray& files); BOOL MakeMount(const CString& strDir, const CString& strVolName, const CString& strCellName, BOOL bRW); BOOL RemoveMount(CStringArray& files); -BOOL RemoveSymlink(const char *); +BOOL RemoveSymlink(const CString& symlink); BOOL GetVolumeInfo(CString strFile, CVolInfo& volInfo); BOOL SetVolInfo(CVolInfo& volInfo); enum WHICH_CELLS { LOCAL_CELL = 0, SPECIFIC_CELL = 1, ALL_CELLS = 2 }; BOOL CheckServers(const CString& strCellName, WHICH_CELLS nCellsToCheck, BOOL bFast); BOOL GetTokenInfo(CStringArray& tokenInfo); -BOOL IsPathInAfs(const CHAR *strPath); -int GetCellName(char *baseNamep, struct afsconf_cell *infop); -long fs_StripDriveLetter(const char *inPathp, char *outPathp, long outSize); -long fs_ExtractDriveLetter(const char *inPathp, char *outPathp); -BOOL IsSymlink(const char * true_name); -BOOL IsMountPoint(const char * name); -UINT MakeSymbolicLink(const char *,const char *); -void ListSymbolicLinkPath(const char *strName,char *strPath,UINT nlenPath); +BOOL IsPathInAfs(const CString& strPath); +BOOL IsSymlink(const CString& name); +BOOL IsMountPoint(const CString& name); +UINT MakeSymbolicLink(const CString&,const CString&); +void ListSymbolicLinkPath(CString&,CString&,UINT nlenPath); BOOL ListSymlink(CStringArray& files); -const char * NetbiosName(void); #endif //__GUI2FS_H__ diff --git a/src/WINNT/client_exp/help.cpp b/src/WINNT/client_exp/help.cpp index 10acc77bf6..2f42628739 100644 --- a/src/WINNT/client_exp/help.cpp +++ b/src/WINNT/client_exp/help.cpp @@ -44,10 +44,9 @@ static BOOL IsWindowsNT (void) } - -void SetHelpPath(const char *pszDefaultHelpFilePath) +void SetHelpPath(LPCTSTR pszDefaultHelpFilePath) { - CString str = pszDefaultHelpFilePath; + CString str(pszDefaultHelpFilePath); int nIndex = str.ReverseFind('\\'); ASSERT(nIndex >= 0); diff --git a/src/WINNT/client_exp/help.h b/src/WINNT/client_exp/help.h index 0dcab65073..3907f795e3 100644 --- a/src/WINNT/client_exp/help.h +++ b/src/WINNT/client_exp/help.h @@ -34,6 +34,6 @@ #define EDIT_PATH_NAME_HELP_ID 46 #define SYMLINK_HELP_ID 47 -void SetHelpPath(const char *pszDefaultHelpFilePath); +void SetHelpPath(LPCTSTR pszDefaultHelpFilePath); void ShowHelp(HWND hWnd, DWORD nHelpID); diff --git a/src/WINNT/client_exp/hourglass.h b/src/WINNT/client_exp/hourglass.h index d78d2fa898..0319f35714 100755 --- a/src/WINNT/client_exp/hourglass.h +++ b/src/WINNT/client_exp/hourglass.h @@ -15,7 +15,7 @@ typedef class HOURGLASS HCURSOR m_OldCursor; public: - HOURGLASS (LPCSTR idCursor = IDC_WAIT) + HOURGLASS (LPTSTR idCursor = IDC_WAIT) { m_OldCursor = GetCursor(); SetCursor (LoadCursor (NULL, idCursor)); diff --git a/src/WINNT/client_exp/klog_dlg.cpp b/src/WINNT/client_exp/klog_dlg.cpp index f715d5a4e9..c7acc85d24 100644 --- a/src/WINNT/client_exp/klog_dlg.cpp +++ b/src/WINNT/client_exp/klog_dlg.cpp @@ -31,17 +31,31 @@ extern "C" { static char THIS_FILE[] = __FILE__; #endif +#ifdef UNICODE +CStringA CStringToCStringA(const CString& str) +{ + CStringA astr(str); + return astr; +} +#define PCCHAR(str) ((char *)(const char *)CStringToCStringA(str)) +#else #define PCCHAR(str) ((char *)(const char *)str) - +#endif ///////////////////////////////////////////////////////////////////////////// // CKlogDlg dialog -int kl_Authenticate(const CString& strCellName, const CString& strName, const CString& strPassword, char **reason) +int kl_Authenticate(const CString& strCellName, const CString& strName, + const CString& strPassword, char **reason) { afs_int32 pw_exp; - return ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, PCCHAR(strName), "", PCCHAR(strCellName), PCCHAR(strPassword), 0, &pw_exp, 0, reason); + return ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, + PCCHAR(strName), "", + PCCHAR(strCellName), + PCCHAR(strPassword), + 0, + &pw_exp, 0, reason); } CKlogDlg::CKlogDlg(CWnd* pParent /*=NULL*/) @@ -88,7 +102,7 @@ BOOL CKlogDlg::OnInitDialog() char defaultCell[256]; long code = cm_GetRootCellName(defaultCell); if (code < 0) - AfxMessageBox("Error determining root cell name."); + AfxMessageBox(_T("Error determining root cell name.")); else m_strCellName = defaultCell; } @@ -107,7 +121,8 @@ void CKlogDlg::OnOK() HOURGLASS hg; if (kl_Authenticate(m_strCellName, m_strName, m_strPassword, &reason)) { - AfxMessageBox(reason); + CString strReason(reason); + AfxMessageBox(strReason); return; } diff --git a/src/WINNT/client_exp/msgs.cpp b/src/WINNT/client_exp/msgs.cpp index b6c854c430..5ec71092df 100644 --- a/src/WINNT/client_exp/msgs.cpp +++ b/src/WINNT/client_exp/msgs.cpp @@ -16,7 +16,7 @@ extern "C" { #include } -#include +#include #include #include "msgs.h" @@ -61,134 +61,134 @@ extern "C" { UINT ShowMessageBox (UINT Id, UINT Button, UINT Help, ...) { CString temp; - char *pszstring, + TCHAR *pszstring, *pszpaste, *pszcut, *pszdone, *pszconvert; - char chread; + TCHAR chread; va_list params; int x; - pszconvert = new char[255]; + pszconvert = new TCHAR[255]; va_start(params, Help); LoadString (temp, Id); pszstring = temp.GetBuffer(512); - strcpy(pszstring,pszstring); + _tcscpy(pszstring,pszstring); temp.ReleaseBuffer(); // Look and see - is there a need to insert chars (95% of the time, there won't) - if (!strstr(pszstring, "%")) { + if (!_tcsstr(pszstring, _T("%"))) { delete pszconvert; return AfxMessageBox(pszstring, Button, Help); } - x = strcspn(pszstring, "%"); - pszdone = new char[512]; - pszcut = new char[512]; - pszpaste = new char[512]; - strcpy(pszcut, &pszstring[x+2]); - strncpy(pszpaste, pszstring, x); - pszpaste[x] = '\0'; + x = _tcscspn(pszstring, _T("%")); + pszdone = new TCHAR[512]; + pszcut = new TCHAR[512]; + pszpaste = new TCHAR[512]; + _tcscpy(pszcut, &pszstring[x+2]); + _tcsncpy(pszpaste, pszstring, x); + pszpaste[x] = _T('\0'); chread = pszstring[x+1]; for ( ; ; ) { switch (chread) { - case 'i' : - case 'd' : + case _T('i') : + case _T('d') : { int anint = va_arg(params, int); - _itoa( anint, pszconvert, 10); + _itot( anint, pszconvert, 10); break; } - case 'u' : + case _T('u') : { UINT anuint = va_arg(params, UINT); - _itoa( anuint, pszconvert, 10); + _itot( anuint, pszconvert, 10); break; } - case 'x' : - case 'X' : + case _T('x') : + case _T('X') : { int ahex = va_arg(params, int); - _itoa( ahex, pszconvert, 16); + _itot( ahex, pszconvert, 16); break; } - case 'g' : - case 'f' : - case 'e' : + case _T('g') : + case _T('f') : + case _T('e') : { double adbl = va_arg(params, double); - _gcvt( adbl, 10, pszconvert); + _stprintf(pszconvert, _T("%g"), adbl); break; } - case 's' : + case _T('s') : { - char *pStr = va_arg(params, char*); - ASSERT(strlen(pStr) <= 255); - strcpy(pszconvert, pStr); + TCHAR *pStr = va_arg(params, TCHAR*); + ASSERT(_tcslen(pStr) <= 255); + _tcscpy(pszconvert, pStr); break; } - case 'l' : + case _T('l') : { chread = pszdone[x+2]; switch(chread) { - case 'x' : + case _T('x') : { long int alhex = va_arg(params, long int); - _ltoa(alhex, pszconvert, 16); - strcpy(pszcut, &pszcut[1]); + _ltot(alhex, pszconvert, 16); + _tcscpy(pszcut, &pszcut[1]); break; } - case 'd' : + case _T('d') : default : { long int along = va_arg(params, long int); - _ltoa( along, pszconvert, 10); + _ltot( along, pszconvert, 10); // For the L, there will be one character after it, // so move ahead another letter - strcpy(pszcut, &pszcut[1]); + _tcscpy(pszcut, &pszcut[1]); break; } } break; } - case 'c' : + case _T('c') : { int letter = va_arg(params, int); - pszconvert[0] = (char)letter; + pszconvert[0] = (TCHAR)letter; pszconvert[1] = '\0'; break; } - case 'a' : + case _T('a') : { CString zeta; - char* lsc; + TCHAR* lsc; UINT ls = va_arg(params, UINT); LoadString (zeta, ls); lsc = zeta.GetBuffer(255); - strcpy(pszconvert, lsc); + _tcscpy(pszconvert, lsc); zeta.ReleaseBuffer(); break; } - case 'o' : + case _T('o') : { CString get = va_arg(params, CString); - char* ex = get.GetBuffer(255); - strcpy(pszconvert,ex); + TCHAR* ex = get.GetBuffer(255); + _tcscpy(pszconvert,ex); get.ReleaseBuffer(); break; } default : { - strcpy(pszconvert, " Could not load message. Invalid %type in string table entry. "); + _tcscpy(pszconvert, _T(" Could not load message. Invalid %type in string table entry. ")); delete pszdone; - pszdone = new char[strlen(pszpaste)+strlen(pszcut)+strlen(pszconvert)+5]; - strcpy(pszdone, pszpaste); - strcat(pszdone, pszconvert); - strcat(pszdone, pszcut); + pszdone = new TCHAR[_tcslen(pszpaste)+_tcslen(pszcut)+_tcslen(pszconvert)+5]; + _tcscpy(pszdone, pszpaste); + _tcscat(pszdone, pszconvert); + _tcscat(pszdone, pszcut); AfxMessageBox(pszdone, Button, Help); delete pszcut; delete pszpaste; @@ -200,14 +200,14 @@ UINT ShowMessageBox (UINT Id, UINT Button, UINT Help, ...) { } // case delete pszdone; - pszdone = new char[strlen(pszpaste)+strlen(pszcut)+strlen(pszconvert)+5]; - strcpy(pszdone, pszpaste); - strcat(pszdone, pszconvert); - strcat(pszdone, pszcut); + pszdone = new TCHAR[_tcslen(pszpaste)+_tcslen(pszcut)+_tcslen(pszconvert)+5]; + _tcscpy(pszdone, pszpaste); + _tcscat(pszdone, pszconvert); + _tcscat(pszdone, pszcut); // Now pszdone holds the entire message. // Check to see if there are more insertions to be made or not - if (!strstr(pszdone, "%")) { + if (!_tcsstr(pszdone, _T("%"))) { UINT rt_type = AfxMessageBox(pszdone, Button, Help); delete pszcut; delete pszpaste; @@ -217,10 +217,10 @@ UINT ShowMessageBox (UINT Id, UINT Button, UINT Help, ...) { } // if // there are more insertions to make, prepare the strings to use. - x = strcspn(pszdone, "%"); - strcpy(pszcut, &pszdone[x+2]); - strncpy(pszpaste, pszdone, x); - pszpaste[x] = '\0'; + x = _tcscspn(pszdone, _T("%")); + _tcscpy(pszcut, &pszdone[x+2]); + _tcsncpy(pszpaste, pszdone, x); + pszpaste[x] = _T('\0'); chread = pszdone[x+1]; } // for @@ -232,137 +232,137 @@ UINT ShowMessageBox (UINT Id, UINT Button, UINT Help, ...) { CString GetMessageString(UINT Id, ...) { CString temp; - char *pszstring, + TCHAR *pszstring, *pszpaste, *pszcut, *pszdone, *pszconvert; - char chread; + TCHAR chread; va_list params; int x; CString strMsg; - pszconvert = new char[255]; + pszconvert = new TCHAR[255]; va_start(params, Id); LoadString (temp, Id); pszstring = temp.GetBuffer(512); - strcpy(pszconvert,pszstring); + _tcscpy(pszconvert,pszstring); temp.ReleaseBuffer(); // Look and see - is there a need to insert chars (95% of the time, there won't) - if (!strstr(pszstring, "%")) { + if (!_tcsstr(pszstring, _T("%"))) { strMsg = pszconvert; delete pszconvert; return strMsg; } - x = strcspn(pszstring, "%"); - pszdone = new char[512]; - pszcut = new char[512]; - pszpaste = new char[512]; - strcpy(pszcut, &pszstring[x+2]); - strncpy(pszpaste, pszstring, x); - pszpaste[x] = '\0'; + x = _tcscspn(pszstring, _T("%")); + pszdone = new TCHAR[512]; + pszcut = new TCHAR[512]; + pszpaste = new TCHAR[512]; + _tcscpy(pszcut, &pszstring[x+2]); + _tcsncpy(pszpaste, pszstring, x); + pszpaste[x] = _T('\0'); chread = pszstring[x+1]; for ( ; ; ) { switch (chread) { - case 'i' : - case 'd' : + case _T('i') : + case _T('d') : { int anint = va_arg(params, int); - _itoa( anint, pszconvert, 10); + _itot( anint, pszconvert, 10); break; } - case 'u' : + case _T('u') : { UINT anuint = va_arg(params, UINT); - _itoa( anuint, pszconvert, 10); + _itot( anuint, pszconvert, 10); break; } - case 'x' : - case 'X' : + case _T('x') : + case _T('X') : { int ahex = va_arg(params, int); - _itoa( ahex, pszconvert, 16); + _itot( ahex, pszconvert, 16); break; } - case 'g' : - case 'f' : - case 'e' : + case _T('g') : + case _T('f') : + case _T('e') : { double adbl = va_arg(params, double); - _gcvt( adbl, 10, pszconvert); + _stprintf(pszconvert, _T("%g"), adbl); break; } - case 's' : + case _T('s') : { - char *pStr = va_arg(params, char*); - ASSERT(strlen(pStr) <= 255); - strcpy(pszconvert, pStr); + TCHAR *pStr = va_arg(params, TCHAR*); + ASSERT(_tcslen(pStr) <= 255); + _tcscpy(pszconvert, pStr); break; } - case 'l' : + case _T('l') : { chread = pszdone[x+2]; switch(chread) { - case 'x' : + case _T('x') : { long int alhex = va_arg(params, long int); - _ltoa(alhex, pszconvert, 16); - strcpy(pszcut, &pszcut[1]); + _ltot(alhex, pszconvert, 16); + _tcscpy(pszcut, &pszcut[1]); break; } - case 'd' : + case _T('d') : default : { long int along = va_arg(params, long int); - _ltoa( along, pszconvert, 10); + _ltot( along, pszconvert, 10); // For the L, there will be one character after it, // so move ahead another letter - strcpy(pszcut, &pszcut[1]); + _tcscpy(pszcut, &pszcut[1]); break; } } break; } - case 'c' : + case _T('c') : { int letter = va_arg(params, int); - pszconvert[0] = (char)letter; - pszconvert[1] = '\0'; + pszconvert[0] = (TCHAR)letter; + pszconvert[1] = _T('\0'); break; } - case 'a' : + case _T('a') : { CString zeta; - char* lsc; + TCHAR* lsc; UINT ls = va_arg(params, UINT); LoadString (zeta, ls); lsc = zeta.GetBuffer(255); - strcpy(pszconvert, lsc); + _tcscpy(pszconvert, lsc); zeta.ReleaseBuffer(); break; } - case 'o' : + case _T('o') : { CString get = va_arg(params, CString); - char* ex = get.GetBuffer(255); - strcpy(pszconvert,ex); + TCHAR* ex = get.GetBuffer(255); + _tcscpy(pszconvert,ex); get.ReleaseBuffer(); break; } default: { - strcpy(pszconvert, " Could not load message. Invalid %type in string table entry. "); + _tcscpy(pszconvert, _T(" Could not load message. Invalid %type in string table entry. ")); delete pszdone; - pszdone = new char[strlen(pszpaste)+strlen(pszcut)+strlen(pszconvert)+5]; - strcpy(pszdone, pszpaste); - strcat(pszdone, pszconvert); - strcat(pszdone, pszcut); + pszdone = new TCHAR[_tcslen(pszpaste)+_tcslen(pszcut)+_tcslen(pszconvert)+5]; + _tcscpy(pszdone, pszpaste); + _tcscat(pszdone, pszconvert); + _tcscat(pszdone, pszcut); strMsg = pszdone; delete pszcut; delete pszpaste; @@ -374,14 +374,14 @@ CString GetMessageString(UINT Id, ...) } // case delete pszdone; - pszdone = new char[strlen(pszpaste)+strlen(pszcut)+strlen(pszconvert)+5]; - strcpy(pszdone, pszpaste); - strcat(pszdone, pszconvert); - strcat(pszdone, pszcut); + pszdone = new TCHAR[_tcslen(pszpaste)+_tcslen(pszcut)+_tcslen(pszconvert)+5]; + _tcscpy(pszdone, pszpaste); + _tcscat(pszdone, pszconvert); + _tcscat(pszdone, pszcut); // Now pszdone holds the entire message. // Check to see if there are more insertions to be made or not - if (!strstr(pszdone, "%")) { + if (!_tcsstr(pszdone, _T("%"))) { strMsg = pszdone; delete pszcut; delete pszpaste; @@ -391,10 +391,10 @@ CString GetMessageString(UINT Id, ...) } // if // there are more insertions to make, prepare the strings to use. - x = strcspn(pszdone, "%"); - strcpy(pszcut, &pszdone[x+2]); - strncpy(pszpaste, pszdone, x); - pszpaste[x] = '\0'; + x = _tcscspn(pszdone, _T("%")); + _tcscpy(pszcut, &pszdone[x+2]); + _tcsncpy(pszpaste, pszdone, x); + pszpaste[x] = _T('\0'); chread = pszdone[x+1]; } // for @@ -404,8 +404,15 @@ CString GetMessageString(UINT Id, ...) void LoadString (CString &Str, UINT id) { - TCHAR szString[ 256 ]; + extern EXPORTED void GetString (LPSTR pszTarget, int idsSource, int cchMax = cchRESOURCE); + + char szString[ 256 ]; GetString (szString, id); +#ifdef UNICODE + CString wstr(szString); + Str = wstr; +#else Str = szString; +#endif } diff --git a/src/WINNT/client_exp/partition_info_dlg.cpp b/src/WINNT/client_exp/partition_info_dlg.cpp index 881bf471b2..9d7d319967 100644 --- a/src/WINNT/client_exp/partition_info_dlg.cpp +++ b/src/WINNT/client_exp/partition_info_dlg.cpp @@ -69,18 +69,18 @@ BOOL CPartitionInfoDlg::OnInitDialog() ASSERT(m_nSize != 0); CString strSize; - strSize.Format("%ld", m_nSize); + strSize.Format(_T("%ld"), m_nSize); CString strFree; - strFree.Format("%ld", m_nFree); + strFree.Format(_T("%ld"), m_nFree); CString strPerUsed; - strPerUsed.Format("%d", ((m_nSize - m_nFree) * 100) / m_nSize); + strPerUsed.Format(_T("%d"), ((m_nSize - m_nFree) * 100) / m_nSize); m_Size.SetWindowText(strSize); m_Free.SetWindowText(strFree); percentUsed = ( double(m_nSize - m_nFree) * 100.0l ) / double(m_nSize); - strPerUsed.Format("%2.2lf", percentUsed ); + strPerUsed.Format(_T("%2.2lf"), percentUsed ); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE diff --git a/src/WINNT/client_exp/set_afs_acl.cpp b/src/WINNT/client_exp/set_afs_acl.cpp index 5da8a51fa0..71da10e5a9 100644 --- a/src/WINNT/client_exp/set_afs_acl.cpp +++ b/src/WINNT/client_exp/set_afs_acl.cpp @@ -104,10 +104,10 @@ BOOL CSetAfsAcl::OnInitDialog() int i; for (i = 0; i < m_Normal.GetSize(); i += 2) - m_NormalRights.AddString(m_Normal[i + 1] + "\t" + m_Normal[i]); + m_NormalRights.AddString(m_Normal[i + 1] + _T("\t") + m_Normal[i]); for (i = 0; i < m_Negative.GetSize(); i += 2) - m_NegativeRights.AddString(m_Negative[i + 1] + "\t" + m_Negative[i]); + m_NegativeRights.AddString(m_Negative[i + 1] + _T("\t") + m_Negative[i]); CenterWindow(); @@ -162,13 +162,13 @@ void CSetAfsAcl::OnAdd() if (bNormal) { m_Normal.Add(name); m_Normal.Add(rights); - m_nCurSel = m_NormalRights.AddString(rights + "\t" + name); + m_nCurSel = m_NormalRights.AddString(rights + _T("\t") + name); m_NormalRights.SetSel(m_nCurSel); m_bShowingNormal = TRUE; } else { m_Negative.Add(name); m_Negative.Add(rights); - m_nCurSel = m_NegativeRights.AddString(rights + "\t" + name); + m_nCurSel = m_NegativeRights.AddString(rights + _T("\t") + name); m_NegativeRights.SetSel(m_nCurSel); m_bShowingNormal = FALSE; } @@ -196,13 +196,13 @@ void CSetAfsAcl::OnCopy() void CSetAfsAcl::ShowRights(const CString& strRights) { - m_ReadPerm.SetCheck((strRights.Find("r") == -1) ? UNCHECKED : CHECKED); - m_WritePerm.SetCheck((strRights.Find("w") == -1) ? UNCHECKED : CHECKED); - m_LookupPerm.SetCheck((strRights.Find("l") == -1) ? UNCHECKED : CHECKED); - m_DeletePerm.SetCheck((strRights.Find("d") == -1) ? UNCHECKED : CHECKED); - m_InsertPerm.SetCheck((strRights.Find("i") == -1) ? UNCHECKED : CHECKED); - m_LockPerm.SetCheck((strRights.Find("k") == -1) ? UNCHECKED : CHECKED); - m_AdminPerm.SetCheck((strRights.Find("a") == -1) ? UNCHECKED : CHECKED); + m_ReadPerm.SetCheck((strRights.Find(_T("r")) == -1) ? UNCHECKED : CHECKED); + m_WritePerm.SetCheck((strRights.Find(_T("w")) == -1) ? UNCHECKED : CHECKED); + m_LookupPerm.SetCheck((strRights.Find(_T("l")) == -1) ? UNCHECKED : CHECKED); + m_DeletePerm.SetCheck((strRights.Find(_T("d")) == -1) ? UNCHECKED : CHECKED); + m_InsertPerm.SetCheck((strRights.Find(_T("i")) == -1) ? UNCHECKED : CHECKED); + m_LockPerm.SetCheck((strRights.Find(_T("k")) == -1) ? UNCHECKED : CHECKED); + m_AdminPerm.SetCheck((strRights.Find(_T("a")) == -1) ? UNCHECKED : CHECKED); } void CSetAfsAcl::OnSelChangeNormalRights() @@ -213,7 +213,7 @@ void CSetAfsAcl::OnSelChangeNormalRights() int nNum = m_NormalRights.GetSelCount(); if (nNum != 1) { - ShowRights(""); + ShowRights(_T("")); EnablePermChanges(FALSE); return; } @@ -236,7 +236,7 @@ void CSetAfsAcl::OnSelChangeNegativeEntries() int nNum = m_NegativeRights.GetSelCount(); if (nNum != 1) { - ShowRights(""); + ShowRights(_T("")); EnablePermChanges(FALSE); return; } @@ -256,19 +256,19 @@ CString CSetAfsAcl::MakeRightsString() CString str; if (m_ReadPerm.GetCheck() == CHECKED) - str += "r"; + str += _T("r"); if (m_LookupPerm.GetCheck() == CHECKED) - str += "l"; + str += _T("l"); if (m_InsertPerm.GetCheck() == CHECKED) - str += "i"; + str += _T("i"); if (m_DeletePerm.GetCheck() == CHECKED) - str += "d"; + str += _T("d"); if (m_WritePerm.GetCheck() == CHECKED) - str += "w"; + str += _T("w"); if (m_LockPerm.GetCheck() == CHECKED) - str += "k"; + str += _T("k"); if (m_AdminPerm.GetCheck() == CHECKED) - str += "a"; + str += _T("a"); return str; } @@ -290,7 +290,7 @@ void CSetAfsAcl::OnPermChange() CString str = MakeRightsString(); (*pRights)[(2 * m_nCurSel) + 1] = str; - str += "\t" + (*pRights)[(2 * m_nCurSel)]; + str += _T("\t") + (*pRights)[(2 * m_nCurSel)]; pRightsList->DeleteString(m_nCurSel); pRightsList->InsertString(m_nCurSel, str); @@ -364,7 +364,7 @@ void CSetAfsAcl::OnNothingSelected() { m_NegativeRights.SetSel(i, FALSE); } - ShowRights(""); // Show no rights + ShowRights(_T("")); // Show no rights EnablePermChanges(FALSE); // Allow no rights changes m_Remove.EnableWindow(FALSE); // Disable remove button } diff --git a/src/WINNT/client_exp/shell_ext.cpp b/src/WINNT/client_exp/shell_ext.cpp index d9231381fb..164ba6c417 100644 --- a/src/WINNT/client_exp/shell_ext.cpp +++ b/src/WINNT/client_exp/shell_ext.cpp @@ -54,7 +54,7 @@ static BOOL IsADir(const CString& strName) { struct _stat statbuf; - if (_stat(strName, &statbuf) < 0) + if (_tstat(strName, &statbuf) < 0) return FALSE; return statbuf.st_mode & _S_IFDIR; @@ -79,9 +79,9 @@ CShellExt::CShellExt() m_bIsOverlayEnabled=FALSE; if (FAILED(hr)) m_pAlloc = NULL; - RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &NPKey); + RegOpenKeyExA(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &NPKey); LSPsize=sizeof(ShellOption); - code=RegQueryValueEx(NPKey, "ShellOption", NULL, + code=RegQueryValueEx(NPKey, _T("ShellOption"), NULL, &LSPtype, (LPBYTE)&ShellOption, &LSPsize); RegCloseKey (NPKey); m_bIsOverlayEnabled=((code==0) && (LSPtype==REG_DWORD) && ((ShellOption & OVERLAYENABLED)!=0)); @@ -206,11 +206,11 @@ STDMETHODIMP CShellExt::XMenuExt::QueryContextMenu(HMENU hMenu,UINT indexMenu, DeleteMenu (hMenu, iItem, MF_BYPOSITION); continue; } - if ((!lstrcmp(szItemText,"&Delete"))&&(pThis->m_bIsSymlink)) { /*this is a symlink - don't present a delete menu!*/ + if ((!lstrcmp(szItemText,_T("&Delete")))&&(pThis->m_bIsSymlink)) { /*this is a symlink - don't present a delete menu!*/ DeleteMenu (hMenu, iItem, MF_BYPOSITION); continue; } - if ((!lstrcmp(szItemText,"Cu&t"))&&(pThis->m_bIsSymlink)) { /*same for cut*/ + if ((!lstrcmp(szItemText,_T("Cu&t")))&&(pThis->m_bIsSymlink)) { /*same for cut*/ DeleteMenu (hMenu, iItem, MF_BYPOSITION); continue; } @@ -411,7 +411,7 @@ STDMETHODIMP CShellExt::XMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) } case IDM_SYMBOLICLINK_ADD: { - CString msg=files.GetAt(0); + CStringA msg(files.GetAt(0)); int i; if ((i=msg.ReverseFind('\\'))>0) msg=msg.Left(i+1); @@ -531,7 +531,7 @@ STDMETHODIMP CShellExt::XMenuExt::GetCommandString(UINT_PTR idCmd, UINT uType, CString strMsg; LoadString (strMsg, nCmdStrID); - strncpy(pszName, strMsg, cchMax); + _tcsncpy((LPTSTR) pszName, strMsg, cchMax); return NOERROR; } @@ -658,10 +658,14 @@ STDMETHODIMP CShellExt::XIconExt::GetOverlayInfo(LPWSTR pwszIconFile if(IsBadWritePtr(pdwFlags, sizeof(DWORD))) return E_INVALIDARG; - HMODULE hModule=GetModuleHandle("shell32.dll"); + HMODULE hModule=GetModuleHandle(_T("shell32.dll")); TCHAR szModule[MAX_PATH]; DWORD z=GetModuleFileName(hModule,szModule,sizeof(szModule)); +#ifndef UNICODE MultiByteToWideChar( CP_ACP,0,szModule,-1,pwszIconFile,cchMax); +#else + _tcsncpy(pwszIconFile, szModule, cchMax); +#endif *pIndex = 30; *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX; return S_OK; @@ -678,7 +682,11 @@ STDMETHODIMP CShellExt::XIconExt::GetPriority(int* pPriority) STDMETHODIMP CShellExt::XIconExt::IsMemberOf(LPCWSTR pwszPath,DWORD dwAttrib) { TCHAR szPath[MAX_PATH]; +#ifdef UNICODE + _tcscpy(szPath, pwszPath); +#else WideCharToMultiByte( CP_ACP,0,pwszPath,-1,szPath,MAX_PATH,NULL,NULL); +#endif if (IsSymlink(szPath)) return S_OK; return S_FALSE; diff --git a/src/WINNT/client_exp/shell_ext.h b/src/WINNT/client_exp/shell_ext.h index b2d4c1a43d..f445e12e80 100644 --- a/src/WINNT/client_exp/shell_ext.h +++ b/src/WINNT/client_exp/shell_ext.h @@ -24,7 +24,7 @@ extern ULONG nICRefCount; // IContextMenu ref count extern ULONG nTPRefCount; // IQueryInfo ref count extern ULONG nXPRefCount; // IPersistFile ref count -#define STR_EXT_TITLE TEXT("AfsClientContextMenu") +#define STR_EXT_TITLE "AfsClientContextMenu" #define STR_REG_PATH TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers") ///////////////////////////////////////////////////////////////////////////// diff --git a/src/WINNT/client_exp/submounts_dlg.cpp b/src/WINNT/client_exp/submounts_dlg.cpp index 35a0ee8d7a..1ebdde5b8b 100644 --- a/src/WINNT/client_exp/submounts_dlg.cpp +++ b/src/WINNT/client_exp/submounts_dlg.cpp @@ -45,10 +45,10 @@ static CSubmountInfo *ReadSubmtInfo(const CString& strShareName) DWORD len; - char pathName[1024]; + TCHAR pathName[1024]; HKEY hkSubmounts; - RegCreateKeyEx( HKEY_LOCAL_MACHINE, + RegCreateKeyExA( HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts", 0, "AFS", @@ -61,7 +61,7 @@ static CSubmountInfo *ReadSubmtInfo(const CString& strShareName) DWORD dwType; DWORD status; len = sizeof(pathName); - status = RegQueryValueEx( hkSubmounts, (LPCSTR)PCCHAR(strShareName), 0, + status = RegQueryValueEx( hkSubmounts, strShareName, 0, &dwType, (LPBYTE)pathName, &len); RegCloseKey( hkSubmounts ); @@ -169,7 +169,7 @@ BOOL CSubmountsDlg::FillSubmtList() DWORD dwIndex; DWORD dwSubmounts; - RegCreateKeyEx( HKEY_LOCAL_MACHINE, + RegCreateKeyExA( HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts", 0, "AFS", @@ -195,7 +195,7 @@ BOOL CSubmountsDlg::FillSubmtList() for ( dwIndex = 0; dwIndex < dwSubmounts; dwIndex ++ ) { - char submountName[256]; + TCHAR submountName[256]; DWORD submountNameLen = sizeof(submountName); RegEnumValue( hkSubmounts, dwIndex, submountName, &submountNameLen, NULL, @@ -222,7 +222,7 @@ void CSubmountsDlg::OnDelete() ASSERT(!strSubmt.IsEmpty()); - strShareName = strSubmt.SpanExcluding("="); + strShareName = strSubmt.SpanExcluding(_T("=")); if (ShowMessageBox(IDS_REALLY_DELETE_SUBMT, MB_YESNO | MB_ICONQUESTION, IDS_REALLY_DELETE_SUBMT, strShareName) != IDYES) return; @@ -251,7 +251,7 @@ static BOOL AddSubmt(CSubmountInfo *pInfo) HOURGLASS hourglass; HKEY hkSubmounts; - RegCreateKeyEx( HKEY_LOCAL_MACHINE, + RegCreateKeyExA( HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts", 0, "AFS", @@ -261,8 +261,9 @@ static BOOL AddSubmt(CSubmountInfo *pInfo) &hkSubmounts, NULL ); - DWORD status = RegSetValueEx( hkSubmounts, PCCHAR(pInfo->GetShareName()), 0, REG_SZ, - (const BYTE *)PCCHAR(pInfo->GetPathName()), strlen(PCCHAR(pInfo->GetPathName())) + 1); + DWORD status = RegSetValueEx( hkSubmounts, pInfo->GetShareName(), 0, REG_SZ, + (const BYTE *)(const TCHAR *) pInfo->GetPathName(), + pInfo->GetPathName().GetLength() + 1); RegCloseKey(hkSubmounts); return (status == ERROR_SUCCESS); @@ -273,7 +274,7 @@ static BOOL DeleteSubmt(CSubmountInfo *pInfo) HOURGLASS hourglass; HKEY hkSubmounts; - RegCreateKeyEx( HKEY_LOCAL_MACHINE, + RegCreateKeyExA( HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts", 0, "AFS", @@ -283,7 +284,7 @@ static BOOL DeleteSubmt(CSubmountInfo *pInfo) &hkSubmounts, NULL ); - DWORD status = RegDeleteValue( hkSubmounts, PCCHAR(pInfo->GetShareName())); + DWORD status = RegDeleteValue( hkSubmounts, pInfo->GetShareName()); RegCloseKey(hkSubmounts); return (status == ERROR_SUCCESS); @@ -325,7 +326,7 @@ void CSubmountsDlg::OnChange() ASSERT(!strSubmt.IsEmpty()); - strShareName = strSubmt.SpanExcluding("="); + strShareName = strSubmt.SpanExcluding(_T("=")); CSubmountInfo *pInfo = FindWork(strShareName); if (pInfo != 0) diff --git a/src/WINNT/client_exp/unlog_dlg.cpp b/src/WINNT/client_exp/unlog_dlg.cpp index 923d846973..b0cf9c6e9f 100644 --- a/src/WINNT/client_exp/unlog_dlg.cpp +++ b/src/WINNT/client_exp/unlog_dlg.cpp @@ -69,7 +69,7 @@ BOOL CUnlogDlg::OnInitDialog() char defaultCell[256]; long code = cm_GetRootCellName(defaultCell); if (code < 0) - AfxMessageBox("Error determining root cell name."); + AfxMessageBox(_T("Error determining root cell name.")); else m_strCellName = defaultCell; } @@ -83,21 +83,24 @@ int kl_Unlog(const CString& strCellName) { struct ktc_principal server; int code; - static char xreason[100]; if (strCellName.IsEmpty()) code = ktc_ForgetAllTokens(); else { - strcpy(server.cell, strCellName); + CStringA astrCellName(strCellName); + + strcpy(server.cell, astrCellName); server.instance[0] = '\0'; strcpy(server.name, "afs"); code = ktc_ForgetToken(&server); } if (code == KTC_NOCM) - AfxMessageBox("AFS service may not have started"); + AfxMessageBox(_T("AFS service may not have started")); else if (code) { - sprintf(xreason, "Unexpected error, code %d", code); + CString xreason; + + xreason.Format(_T("Unexpected error, code %d"), code); AfxMessageBox(xreason); } diff --git a/src/WINNT/client_exp/volumeinfo.cpp b/src/WINNT/client_exp/volumeinfo.cpp index d200ef73e5..f077c4c829 100644 --- a/src/WINNT/client_exp/volumeinfo.cpp +++ b/src/WINNT/client_exp/volumeinfo.cpp @@ -233,10 +233,15 @@ void CVolumeInfo::ShowInfo() if (nQuota != 0) { LONG nPercentUsed = (m_pVolInfo[i].m_nUsed * 100) / nQuota; - strEntry.Format("%s\t%s\t%ld\t%ldK\t%ldK\t%ld%%", m_pVolInfo[i].m_strFileName, m_pVolInfo[i].m_strName, - m_pVolInfo[i].m_nID, nQuota, m_pVolInfo[i].m_nUsed, nPercentUsed); + strEntry.Format(_T("%s\t%s\t%ld\t%ldK\t%ldK\t%ld%%"), + m_pVolInfo[i].m_strFileName, + m_pVolInfo[i].m_strName, + m_pVolInfo[i].m_nID, nQuota, + m_pVolInfo[i].m_nUsed, nPercentUsed); } else { - strEntry.Format("%s\t%s\t%ld\tUnlimited\t%ldK", m_pVolInfo[i].m_strFileName, m_pVolInfo[i].m_strName, + strEntry.Format(_T("%s\t%s\t%ld\tUnlimited\t%ldK"), + m_pVolInfo[i].m_strFileName, + m_pVolInfo[i].m_strName, m_pVolInfo[i].m_nID, m_pVolInfo[i].m_nUsed); } } diff --git a/src/config/NTMakefile.i386_w2k b/src/config/NTMakefile.i386_w2k index ac879049e6..872a2c93ef 100644 --- a/src/config/NTMakefile.i386_w2k +++ b/src/config/NTMakefile.i386_w2k @@ -37,6 +37,10 @@ #sanity checks +!IF ("$(CPU)" != "x86") +CPU=i386 +!ENDIF + !IF ("$(CPU)" != "i386") !ERROR Platform SDK not configured for i386 !ENDIF @@ -82,7 +86,7 @@ INCLUDE = $(AFSDEV_INCLUDE) LIB = $(AFSDEV_LIB) #define used in WinNT/2000 installation and program version display -AFSPRODUCT_VER_MAJOR=0 +AFSPRODUCT_VER_MAJOR=2 AFSPRODUCT_VER_MINOR=0 AFSPRODUCT_VER_PATCH=0 AFSPRODUCT_VER_BUILD=0 @@ -223,6 +227,7 @@ afscdefs =\ -DAFS_64BIT_ENV \ -DAFS_64BIT_CLIENT \ -DAFS_LARGEFILE_ENV \ + -DAFS_OLD_COM_ERR \ $(AFSDEV_AUXCDEFINES) # Compiler switches (except include paths and preprocessor defines) diff --git a/src/libafsauthent/afsauthent.def b/src/libafsauthent/afsauthent.def index 4dfa492cf4..2e59483e22 100644 --- a/src/libafsauthent/afsauthent.def +++ b/src/libafsauthent/afsauthent.def @@ -115,3 +115,4 @@ EXPORTS VOTE_GetSyncSite @113 ubik_RefreshConn @114 rx_SetSecurityConfiguration @115 + pioctl_utf8 @116 diff --git a/src/ntbuild.bat b/src/ntbuild.bat index 846b6591f9..6b0fd7678b 100755 --- a/src/ntbuild.bat +++ b/src/ntbuild.bat @@ -53,6 +53,9 @@ set NTDDKDIR=c:\progra~1\micros~5 REM Location of netmpr.h/netspi.h (from Windows 95/98 DDK - 8.3 short name) SET W9XDDKDIR=c:\progra~1\micros~6 +REM Location of Microsoft IDN Normalization SDK +set MSIDNNLS=C:\progra~1\MI5913~1 + REM ######################################################################## REM NTMakefile optional definitions: REM @@ -113,7 +116,7 @@ REM AFSDEV_BIN = default build binary directories set AFSDEV_BUILDTYPE=%AFSBLD_TYPE% -set AFSDEV_INCLUDE=%MSSDKDIR%\include;%MSVCDIR%\include +set AFSDEV_INCLUDE=%MSSDKDIR%\include;%MSVCDIR%\include;%MSIDNNLS%\include IF "%AFSVER_CL%" == "1400" set AFSDEV_INCLUDE=%AFSDEV_INCLUDE%;%MSVCDIR%\atlmfc\include IF "%AFSVER_CL%" == "1310" set AFSDEV_INCLUDE=%AFSDEV_INCLUDE%;%MSVCDIR%\atlmfc\include IF "%AFSVER_CL%" == "1300" set AFSDEV_INCLUDE=%AFSDEV_INCLUDE%;%MSVCDIR%\atlmfc\include diff --git a/src/sys/pioctl_nt.c b/src/sys/pioctl_nt.c index 009d874f5f..c385f74cd4 100644 --- a/src/sys/pioctl_nt.c +++ b/src/sys/pioctl_nt.c @@ -49,6 +49,9 @@ RCSID static char AFSConfigKeyName[] = AFSREG_CLT_SVC_PARAM_SUBKEY; +static const char utf8_prefix[] = UTF8_PREFIX; +static const int utf8_prefix_size = sizeof(utf8_prefix) - sizeof(char); + #define FS_IOCTLREQUEST_MAXSIZE 8192 /* big structure for representing and storing an IOCTL request */ typedef struct fs_ioctlRequest { @@ -763,7 +766,7 @@ UnmarshallLong(fs_ioctlRequest_t * reqp, long *valp) /* includes marshalling NULL pointer as a null (0 length) string */ static long -MarshallString(fs_ioctlRequest_t * reqp, char *stringp) +MarshallString(fs_ioctlRequest_t * reqp, char *stringp, int is_utf8) { int count; @@ -772,6 +775,10 @@ MarshallString(fs_ioctlRequest_t * reqp, char *stringp) else count = 1; + if (is_utf8) { + count += utf8_prefix_size; + } + /* watch for buffer overflow */ if ((reqp->mp - reqp->data) + count > sizeof(reqp->data)) { if ( IoctlDebug() ) @@ -779,6 +786,12 @@ MarshallString(fs_ioctlRequest_t * reqp, char *stringp) return -1; } + if (is_utf8) { + memcpy(reqp->mp, utf8_prefix, utf8_prefix_size); + reqp->mp += utf8_prefix_size; + count -= utf8_prefix_size; + } + if (stringp) memcpy(reqp->mp, stringp, count); else @@ -906,8 +919,8 @@ fs_GetFullPath(char *pathp, char *outPathp, long outSize) return 0; } -long -pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow) +static long +pioctl_int(char *pathp, long opcode, struct ViceIoctl *blobp, int follow, int is_utf8) { fs_ioctlRequest_t preq; long code; @@ -945,7 +958,7 @@ pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow) strcpy(fullPath, ""); } - MarshallString(&preq, fullPath); + MarshallString(&preq, fullPath, is_utf8); if (blobp->in_size) { if (blobp->in_size > sizeof(preq.data) - (preq.mp - preq.data)*sizeof(char)) { errno = E2BIG; @@ -989,3 +1002,16 @@ pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow) CloseHandle(reqHandle); return 0; } + +long +pioctl_utf8(char * pathp, long opcode, struct ViceIoctl * blobp, int follow) +{ + return pioctl_int(pathp, opcode, blobp, follow, TRUE); +} + +long +pioctl(char * pathp, long opcode, struct ViceIoctl * blobp, int follow) +{ + return pioctl_int(pathp, opcode, blobp, follow, FALSE); +} + diff --git a/src/sys/pioctl_nt.h b/src/sys/pioctl_nt.h index bdccd4516a..d84cfe75e6 100644 --- a/src/sys/pioctl_nt.h +++ b/src/sys/pioctl_nt.h @@ -28,4 +28,7 @@ typedef struct ViceIoctl { extern long pioctl(char *pathp, long opcode, struct ViceIoctl *blob, int follow); +extern long pioctl_utf8(char *pathp, long opcode, struct ViceIoctl *blob, + int follow); + #endif /* OPENAFS_AFS_PIOCTL_H */