#include #include "cdinst.h" VOID ParseCmdLine(LPSTR pszCmdLine) { LPSTR pszCurrArg; LPSTR pszPtr; GetNextField(&pszCmdLine, "/", 0); // point to the first argument while ((pszCurrArg = GetNextField(&pszCmdLine, "/", 0)) != NULL) { switch (*pszCurrArg) { case 's': case 'S': if (*++pszCurrArg == ':') pszCurrArg++; // Source dir from where to grab the files if ((pszPtr = Trim(GetNextField(&pszCurrArg, ",", REMOVE_QUOTES))) != NULL) lstrcpy(g_szSrcDir, pszPtr); else *g_szSrcDir = '\0'; break; case 'd': case 'D': if (*++pszCurrArg == ':') pszCurrArg++; // Destination dir to where to copy the files if ((pszPtr = Trim(GetNextField(&pszCurrArg, ",", REMOVE_QUOTES))) != NULL) lstrcpy(g_szDstDir, pszPtr); else *g_szDstDir = '\0'; break; default: // ignore these arguments break; } } } DWORD ReadSectionFromInf(LPCSTR pcszSecName, LPSTR *ppszBuf, PDWORD pdwBufLen, LPCSTR pcszInfName) { DWORD dwRet; // set the file attrib of pcszInfName to NORMAL so that GetPrivateProfileSecion doesn't // barf in case pcszInfName is read only SetFileAttributes(pcszInfName, FILE_ATTRIBUTE_NORMAL); // keep allocating buffers in increasing size of 1K till the entire section is read *ppszBuf = NULL; *pdwBufLen = 1024; do { if (*ppszBuf != NULL) LocalFree(*ppszBuf); // free the previously allocated memory if (*pdwBufLen == MAX_BUF_LEN) (*pdwBufLen)--; // 32K - 1 is the size limit for a section if ((*ppszBuf = (LPSTR) LocalAlloc(LPTR, *pdwBufLen)) == NULL) { *pdwBufLen = 0; return 0; } } while ((dwRet = GetPrivateProfileSection(pcszSecName, *ppszBuf, *pdwBufLen, pcszInfName)) == *pdwBufLen - 2 && (*pdwBufLen += 1024) <= MAX_BUF_LEN); return dwRet; } BOOL PathExists(LPCSTR pcszDir) { DWORD dwAttrib = GetFileAttributes(pcszDir); return (dwAttrib != (DWORD) -1) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY); } BOOL FileExists(LPCSTR pcszFileName) { DWORD dwAttrib = GetFileAttributes(pcszFileName); if (dwAttrib == (DWORD) -1) return FALSE; return !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY); } DWORD FileSize(LPCSTR pcszFile) { DWORD dwFileSize = 0; WIN32_FIND_DATA FindFileData; HANDLE hFile; if (pcszFile == NULL || *pcszFile == '\0') return dwFileSize; if ((hFile = FindFirstFile(pcszFile, &FindFileData)) != INVALID_HANDLE_VALUE) { // assumption here is that the size of the file doesn't exceed 4 gigs dwFileSize = FindFileData.nFileSizeLow; FindClose(hFile); } return dwFileSize; } LPSTR AddPath(LPSTR pszPath, LPCSTR pcszFileName) { LPSTR pszPtr; if (pszPath == NULL) return NULL; pszPtr = pszPath + lstrlen(pszPath); if (pszPtr > pszPath && *CharPrev(pszPath, pszPtr) != '\\') *pszPtr++ = '\\'; if (pcszFileName != NULL) lstrcpy(pszPtr, pcszFileName); else *pszPtr = '\0'; return pszPath; } BOOL PathIsUNCServer(LPCSTR pcszPath) { if (PathIsUNC(pcszPath)) { int i = 0; for ( ; pcszPath != NULL && *pcszPath; pcszPath = CharNext(pcszPath)) if (*pcszPath == '\\') i++; return i == 2; } return FALSE; } BOOL PathIsUNCServerShare(LPCSTR pcszPath) { if (PathIsUNC(pcszPath)) { int i = 0; for ( ; pcszPath != NULL && *pcszPath; pcszPath = CharNext(pcszPath)) if (*pcszPath == '\\') i++; return i == 3; } return FALSE; } BOOL PathCreatePath(LPCSTR pcszPathToCreate) { CHAR szPath[MAX_PATH]; LPSTR pszPtr; if (pcszPathToCreate == NULL || lstrlen(pcszPathToCreate) <= 3) return FALSE; // eliminate relative paths if (!PathIsFullPath(pcszPathToCreate) && !PathIsUNC(pcszPathToCreate)) return FALSE; if (PathIsUNCServer(pcszPathToCreate) || PathIsUNCServerShare(pcszPathToCreate)) return FALSE; lstrcpy(szPath, pcszPathToCreate); // chop off the trailing backslash, if it exists pszPtr = CharPrev(szPath, szPath + lstrlen(szPath)); if (*pszPtr == '\\') *pszPtr = '\0'; // if it's a UNC path, seek up to the first dir after the share name if (PathIsUNC(szPath)) { INT i; pszPtr = &szPath[2]; for (i = 0; i < 2; i++) for ( ; *pszPtr != '\\'; pszPtr = CharNext(pszPtr)) ; pszPtr = CharNext(pszPtr); } else // otherwise, just point to the beginning of the first dir pszPtr = &szPath[3]; for ( ; *pszPtr; pszPtr = CharNext(pszPtr)) { CHAR ch; // skip the non-backslash chars while (*pszPtr && *pszPtr != '\\') pszPtr = CharNext(pszPtr); // save the current char ch = *pszPtr; *pszPtr = '\0'; if (GetFileAttributes(szPath) == 0xFFFFFFFF) // dir doesn't exist if (!CreateDirectory(szPath, NULL)) return FALSE; // restore the current char *pszPtr = ch; } return TRUE; } VOID ErrorMsg(UINT uStringID) { ErrorMsg(uStringID, "", ""); } VOID ErrorMsg(UINT uStringID, LPCSTR pcszParam1, LPCSTR pcszParam2) { LPSTR pszTextString; pszTextString = FormatMessageString(uStringID, pcszParam1, pcszParam2); MessageBox(NULL, (pszTextString != NULL) ? pszTextString : "", g_szTitle, MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_OK); if (pszTextString != NULL) LocalFree(pszTextString); } INT ErrorMsg(UINT uStringID, DWORD dwParam1, DWORD dwParam2) { INT iRet; LPSTR pszTextString; pszTextString = FormatMessageString(uStringID, dwParam1, dwParam2); iRet = MessageBox(NULL, (pszTextString != NULL) ? pszTextString : "", g_szTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2 | MB_SETFOREGROUND); if (pszTextString != NULL) LocalFree(pszTextString); return iRet; } LPSTR FormatMessageString(UINT uStringID, LPCSTR pcszParam1, LPCSTR pcszParam2) { CHAR szBuf[512]; if (LoadString(g_hInst, uStringID, szBuf, sizeof(szBuf))) { LPSTR pszTextString; if ((pszTextString = FormatString(szBuf, pcszParam1, pcszParam2)) != NULL) return pszTextString; } return NULL; } LPSTR FormatMessageString(UINT uStringID, DWORD dwParam1, DWORD dwParam2) { CHAR szBuf[512]; if (LoadString(g_hInst, uStringID, szBuf, sizeof(szBuf))) { LPSTR pszTextString; if ((pszTextString = FormatString(szBuf, dwParam1, dwParam2)) != NULL) return pszTextString; } return NULL; } LPSTR FormatString(LPCSTR pcszFormatString, ...) { va_list vaArgs; LPSTR pszOutString = NULL; va_start(vaArgs, pcszFormatString); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_STRING, (LPCVOID) pcszFormatString, 0, 0, (PSTR) &pszOutString, 0, &vaArgs); va_end(vaArgs); return pszOutString; } LPSTR GetNextField(LPSTR *ppszData, LPCSTR pcszDeLims, DWORD dwFlags) // If (dwFlags & IGNORE_QUOTES) is TRUE, then look for any char in pcszDeLims in *ppszData. If found, // replace it with the '\0' char and set *ppszData to point to the beginning of the next field and return // pointer to current field. // // If (dwFlags & IGNORE_QUOTES) is FALSE, then look for any char in pcszDeLims outside of balanced quoted sub-strings // in *ppszData. If found, replace it with the '\0' char and set *ppszData to point to the beginning of // the next field and return pointer to current field. // // If (dwFlags & REMOVE_QUOTES) is TRUE, then remove the surrounding quotes and replace two consecutive quotes by one. // // NOTE: If IGNORE_QUOTES and REMOVE_QUOTES are both specified, then IGNORE_QUOTES takes precedence over REMOVE_QUOTES. // // If you just want to remove the quotes from a string, call this function as // GetNextField(&pszData, "\"" or "'" or "", REMOVE_QUOTES). // // If you call this function as GetNextField(&pszData, "\"" or "'" or "", 0), you will get back the // entire pszData as the field. // { LPSTR pszRetPtr, pszPtr; BOOL fWithinQuotes = FALSE, fRemoveQuote; CHAR chQuote; if (ppszData == NULL || *ppszData == NULL || **ppszData == '\0') return NULL; for (pszRetPtr = pszPtr = *ppszData; *pszPtr; pszPtr = CharNext(pszPtr)) { if (!(dwFlags & IGNORE_QUOTES) && (*pszPtr == '"' || *pszPtr == '\'')) { fRemoveQuote = FALSE; if (*pszPtr == *(pszPtr + 1)) // two consecutive quotes become one { pszPtr++; if (dwFlags & REMOVE_QUOTES) fRemoveQuote = TRUE; else { // if pcszDeLims is '"' or '\'', then *pszPtr == pcszDeLims would // be TRUE and we would break out of the loop against the design specs; // to prevent this just continue continue; } } else if (!fWithinQuotes) { fWithinQuotes = TRUE; chQuote = *pszPtr; // save the quote char fRemoveQuote = dwFlags & REMOVE_QUOTES; } else { if (*pszPtr == chQuote) // match the correct quote char { fWithinQuotes = FALSE; fRemoveQuote = dwFlags & REMOVE_QUOTES; } } if (fRemoveQuote) { // shift the entire string one char to the left to get rid of the quote char MoveMemory(pszPtr, pszPtr + 1, lstrlen(pszPtr)); } } // BUGBUG: Is type casting pszPtr to UNALIGNED necessary? -- copied it from ANSIStrChr // check if pszPtr is pointing to one of the chars in pcszDeLims if (!fWithinQuotes && ANSIStrChr(pcszDeLims, (WORD) (IsDBCSLeadByte(*pszPtr) ? *((UNALIGNED WORD *) pszPtr) : *pszPtr)) != NULL) break; } // NOTE: if fWithinQuotes is TRUE here, then we have an unbalanced quoted string; but we don't care! // the entire string after the beginning quote becomes the field if (*pszPtr) // pszPtr is pointing to a char in pcszDeLims { *ppszData = CharNext(pszPtr); // save the pointer to the beginning of next field in *ppszData *pszPtr = '\0'; // replace the DeLim char with the '\0' char } else *ppszData = pszPtr; // we have reached the end of the string; next call to this function // would return NULL return pszRetPtr; } LPSTR Trim(LPSTR pszData) // Trim the leading and trailing white space chars in pszData { LPSTR pszRetPtr; if (pszData == NULL) return NULL; // trim the leading white space chars for ( ; *pszData; pszData = CharNext(pszData)) if (!IsSpace(*pszData)) break; // save the return ptr pszRetPtr = pszData; // go to the end and start trimming the trailing white space chars pszData += lstrlen(pszData); while ((pszData = CharPrev(pszRetPtr, pszData)) != pszRetPtr) if (!IsSpace(*pszData)) break; if (*pszData) { pszData = CharNext(pszData); *pszData = '\0'; } return pszRetPtr; } // copied from \\trango\slmadd\src\shell\shlwapi\strings.c /* * StrChr - Find first occurrence of character in string * Assumes lpStart points to start of null terminated string * wMatch is the character to match * returns ptr to the first occurrence of ch in str, NULL if not found. */ LPSTR FAR ANSIStrChr(LPCSTR lpStart, WORD wMatch) { for ( ; *lpStart; lpStart = CharNext(lpStart)) { // (ChrCmp returns FALSE when characters match) if (!ChrCmpA_inline(*(UNALIGNED WORD FAR *)lpStart, wMatch)) return((LPSTR)lpStart); } return (NULL); } // copied from \\trango\slmadd\src\shell\shlwapi\strings.c /* * StrRChr - Find last occurrence of character in string * Assumes lpStart points to start of null terminated string * wMatch is the character to match * returns ptr to the last occurrence of ch in str, NULL if not found. */ LPSTR FAR ANSIStrRChr(LPCSTR lpStart, WORD wMatch) { LPCSTR lpFound = NULL; for ( ; *lpStart; lpStart = CharNext(lpStart)) { // (ChrCmp returns FALSE when characters match) if (!ChrCmpA_inline(*(UNALIGNED WORD FAR *)lpStart, wMatch)) lpFound = lpStart; } return ((LPSTR)lpFound); } // copied from \\trango\slmadd\src\shell\shlwapi\strings.c /* * ChrCmp - Case sensitive character comparison for DBCS * Assumes w1, wMatch are characters to be compared * Return FALSE if they match, TRUE if no match */ __inline BOOL ChrCmpA_inline(WORD w1, WORD wMatch) { /* Most of the time this won't match, so test it first for speed. */ if (LOBYTE(w1) == LOBYTE(wMatch)) { if (IsDBCSLeadByte(LOBYTE(w1))) { return(w1 != wMatch); } return FALSE; } return TRUE; }